3

次のようなコントロールを作成したい:

  • ItemsControl から派生し、
  • 列挙型のリストにバインドできます。
  • 列挙型ごとに、RadioButton が表示されます。
  • 特定の RadioButton が選択されると、SelectedItem には RadioButton に関連付けられた列挙値が含まれます。

上記のリストの最初の 3 点は達成できましたが、4 番目の項目に問題があります。アイテム コンテナ クラスの実装が間違っているか、generic.xaml のアイテム テンプレート定義が間違っている可能性があります。

アイテム コンテナは次のようになります。

public class MyEnumSelectorItem : ContentControl
{
public static readonly DependencyProperty IsSelectedProperty;

static MyEnumSelectorItem()
{
    IsSelectedProperty = Selector.IsSelectedProperty.AddOwner(typeof(MyEnumSelectorItem));
}

public bool IsSelected
{
    get { return (bool)GetValue(IsSelectedProperty); }
    set { SetValue(IsSelectedProperty, value); }
}

static readonly DependencyProperty ModeProperty = 
    DependencyProperty.Register("Mode", typeof(MyEnum), typeof(MyEnumSelector), new PropertyMetadata());
public MyEnum Mode
{
    get { return (MyEnum)GetValue(ModeProperty); }
    set { SetValue(ModeProperty, value); }
}
}

アイテム コンテナ タイプは、メソッド オーバーライドSystem.Windows.Controls.Primitives.Selectorを使用してセレクタ コントロール ( から派生) に関連付けられます。IsItemItsOwnContainerOverride/GetContainerForItemOverride/PrepareContainerForItemOverride

generic.xaml の関連するフラグメントは次のようになります。

<Style TargetType="{x:Type controls:MyEnumSelector}">
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <RadioButton Content="{Binding}" 
                     IsChecked="{Binding IsSelected, Mode=TwoWay}" 
                     GroupName="enumSelector" Height="25" FontWeight="Bold"  />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

上記は、IsSelected プロパティの正しいバインドにより、自動的に SelectedItem プロパティが設定されることを前提としています (これは正しいと思いますよね?)。

4

1 に答える 1

2

ここでは電話をかけるだけでSelector.IsSelectedProperty.AddOwnerは十分ではないようです。

ILSpyListBoxItemの のコードを見ると、Selected/Unselected イベントの発生など、選択されたアイテムとセレクター自体の間で同期するために、他にもいくつかのことが行われている可能性があることがわかります

static ListBoxItem()
{
    ListBoxItem.IsSelectedProperty = Selector.IsSelectedProperty.AddOwner(typeof(ListBoxItem), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, new PropertyChangedCallback(ListBoxItem.OnIsSelectedChanged)));
    ListBoxItem.SelectedEvent = Selector.SelectedEvent.AddOwner(typeof(ListBoxItem));
    ListBoxItem.UnselectedEvent = Selector.UnselectedEvent.AddOwner(typeof(ListBoxItem));
    ...
}

private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ListBoxItem listBoxItem = d as ListBoxItem;
    bool flag = (bool)e.NewValue;
    Selector parentSelector = listBoxItem.ParentSelector;
    if (parentSelector != null)
    {
        parentSelector.RaiseIsSelectedChangedAutomationEvent(listBoxItem, flag);
    }
    if (flag)
    {
        listBoxItem.OnSelected(new RoutedEventArgs(Selector.SelectedEvent, listBoxItem));
    }
    else
    {
        listBoxItem.OnUnselected(new RoutedEventArgs(Selector.UnselectedEvent, listBoxItem));
    }
    listBoxItem.UpdateVisualState();
}

これで実際に問題が解決するかどうかを自分で試したことはありませんが、始めるには良い場所だと思います。ListBoxItemアイテムをではなくから派生させることも検討する必要がありますContentControl

于 2012-09-09T20:37:56.167 に答える