0

ユーザー定義の項目リストに加えて、「すべて選択」項目を含む WPF CustomControl CheckComboBox を作成しようとしています。「すべて選択」を選択すると、それに応じてリスト内のすべての項目がチェックされます。「すべて選択」項目がクリックされた場合、どのように対応すればよいですか? いろいろ試してみたのですが、CheckComboBox.csのプロパティ「SelectAll」が一向に入力されません。

これが私の現在のコードです。

Generic.xaml

<Style TargetType="{x:Type local:CheckComboBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CheckComboBox}">
                    <ComboBox SelectedItem="{TemplateBinding SelectedItem}"
                              SelectedValue="{TemplateBinding SelectedValue}"
                              SelectedValuePath="{TemplateBinding SelectedValuePath}"
                              DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
                              IsTextSearchEnabled="{TemplateBinding IsTextSearchEnabled}"
                              ItemTemplate="{TemplateBinding ItemTemplate}"
                              x:Name="InnerComboBox" >

                        <ComboBox.Resources>
                            <ResourceDictionary>
                                <CheckBox x:Key="allItem" Content="All" IsChecked="{Binding SelectAll, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
                                <CollectionViewSource x:Key="items" Source="{Binding ComboBoxItems, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
                            </ResourceDictionary>
                        </ComboBox.Resources>

                        <ComboBox.ItemsSource>
                            <CompositeCollection>
                                <ComboBoxItem Content="{Binding Source={StaticResource allItem}}"/>
                                <CollectionContainer Collection="{Binding Source={StaticResource items}}" />
                            </CompositeCollection>
                        </ComboBox.ItemsSource>

                    </ComboBox>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding IsSelected}" Content="{Binding Text}" VerticalAlignment="Center" />
                    </StackPanel>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

CheckComboBox.cs

   public class CheckComboBox : ComboBox
    {
        public class CheckComboBoxItem
        {
            public CheckComboBoxItem(bool isSelected, string text)
            {
                IsSelected = isSelected;
                Text = text;
            }
            public bool IsSelected { get; set; }
            public string Text { get; set; }
        }

        static CheckComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckComboBox), new FrameworkPropertyMetadata(typeof(CheckComboBox)));
        }

        public static readonly DependencyProperty ComboBoxItemsProperty =
            DependencyProperty.Register("ComboBoxItems", typeof (ObservableCollection<CheckComboBoxItem>), typeof (CheckComboBox), new PropertyMetadata(default(ObservableCollection<CheckComboBoxItem>)));

        public ObservableCollection<CheckComboBoxItem> ComboBoxItems
        {
            get { return (ObservableCollection<CheckComboBoxItem>) GetValue(ComboBoxItemsProperty); }
            set { SetValue(ComboBoxItemsProperty, value); }
        }

        public static readonly DependencyProperty SelectAllProperty =
            DependencyProperty.Register("SelectAll", typeof (bool), typeof (CheckComboBox), new PropertyMetadata(default(bool)));

        public bool SelectAll
        {
            get { return (bool) GetValue(SelectAllProperty); }
            set
            {
                foreach (var item in ComboBoxItems)
                {
                    item.IsSelected = value;
                }
                SetValue(SelectAllProperty, value);
            }
        }
    }
}

テストデータの設定:

ObservableCollection<CheckComboBox.CheckComboBoxItem> checkComboBoxItems = new ObservableCollection<CheckComboBox.CheckComboBoxItem>();
checkComboBoxItems.Add(new CheckComboBox.CheckComboBoxItem(false, "Generation 0"));
checkComboBoxItems.Add(new CheckComboBox.CheckComboBoxItem(true, "Generation 1"));
checkComboBoxItems.Add(new CheckComboBox.CheckComboBoxItem(false, "Generation 2"));
checkComboBox1.ComboBoxItems = checkComboBoxItems;

編集: CheckComboBox.cs のSelectAll DependencyProperty を次のコードに置き換えましたが、OnSelectAll が入力されていません 。SelectAll コンボボックスは、何らかの理由でバインドをトリガーしません。

public static readonly DependencyProperty SelectAllProperty =
        DependencyProperty.Register("SelectAll",
                    typeof (bool),
                    typeof (CheckComboBox),
                    new FrameworkPropertyMetadata(false,
                        FrameworkPropertyMetadataOptions.AffectsRender,
                        new PropertyChangedCallback(OnSelectAll)));

private static void OnSelectAll(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    CheckComboBox checkComboBox = (CheckComboBox)d;
    foreach (var item in checkComboBox.ComboBoxItems)
    {
        item.IsSelected = (bool) e.NewValue;
    }
}

public bool SelectAll
{
    get { return (bool) GetValue(SelectAllProperty); }
    set { SetValue(SelectAllProperty, value); }
}    
4

1 に答える 1

1

最後に、「SelectAll」プロパティをトリガーする方法を見つけました。次の点に注意してください。

<ComboBoxItem>
    <CheckBox ... />
</ComboBoxItem>

Generic.xaml

...
<ComboBox.Resources>
    <ResourceDictionary>
        <CollectionViewSource x:Key="items" Source="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
    </ResourceDictionary>
</ComboBox.Resources>

<ComboBox.ItemsSource>
    <CompositeCollection>
        <ComboBoxItem>
            <CheckBox Content="All" IsChecked="{Binding SelectAll, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
        </ComboBoxItem>
        <CollectionContainer Collection="{Binding Source={StaticResource items}}" />
    </CompositeCollection>
</ComboBox.ItemsSource>
...

CheckComboBox.cs

public class CheckComboBox : ComboBox
{
    public class CheckComboBoxItem : ModelBase
    {
        public CheckComboBoxItem(bool isSelected, string text)
        {
            IsSelected = isSelected;
            Text = text;
        }

        private bool _isSelected;
        public bool IsSelected 
        { 
            get { return _isSelected; }
            set { Set(() => IsSelected, ref _isSelected, value); }
        }

        private string _text;
        public string Text 
        { 
            get { return _text; }
            set { Set(() => Text, ref _text, value); }
        }
    }

    static CheckComboBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckComboBox), new FrameworkPropertyMetadata(typeof(CheckComboBox)));
    }

    public static readonly DependencyProperty SelectAllProperty =
        DependencyProperty.Register("SelectAll",
                                    typeof (bool),
                                    typeof (CheckComboBox),
                                    new FrameworkPropertyMetadata(false,
                                        FrameworkPropertyMetadataOptions.AffectsRender,
                                        new PropertyChangedCallback(OnSelectAll)));

    private static void OnSelectAll(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CheckComboBox checkComboBox = (CheckComboBox)d;
        IEnumerable<CheckComboBoxItem> items = (IEnumerable<CheckComboBoxItem>) checkComboBox.ItemsSource;
        foreach (var item in items)
        {
            item.IsSelected = (bool) e.NewValue;
        }
    }

    public bool SelectAll
    {
        get { return (bool) GetValue(SelectAllProperty); }
        set { SetValue(SelectAllProperty, value); }
    }
}

ここで、別の項目の選択が解除されたときに [すべて選択] チェック ボックスを自動的に選択解除する方法を見つけなければなりません。

于 2012-12-21T11:02:02.133 に答える