Привязка / запуск "Выбрать все"-CheckBox ComboBoxItem в WPF
Я пытаюсь создать WPC CustomControl CheckComboBox с элементом "Выбрать все" в дополнение к определенному пользователем списку элементов. Когда выбран "Выбрать все", все элементы в списке должны быть проверены соответствующим образом. Как я могу реагировать на нажатие на элемент "Выбрать все"? Я много чего перепробовал, но свойство "SelectAll" в CheckComboBox.cs никогда не вводилось.
Это мой текущий код.
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;
Редактировать:Заменить SelectAll DependencyProperty в CheckComboBox.cs следующим кодом, но 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); }
}
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); }
}
}
Теперь мне просто нужно выяснить, как автоматически снимать флажок "Выбрать все", когда отменяется выбор другого элемента.