0

除了用户定义的项目列表之外,我正在尝试制作一个带有“全选”项目的 WPF CustomControl CheckComboBox。选择“全选”时,应相应检查列表中的所有项目。如何对单击的“全选”项目采取行动?我尝试了很多东西,但从未输入 CheckComboBox.cs 中的属性“SelectAll”。

这是我当前的代码。

通用的.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>

通用的.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 回答