取消选中其中一个子复选框应取消选中WPF MVVM模式中的父复选框

时间:2017-08-07 07:04:26

标签: c# wpf xaml checkbox mvvm

前两种方式对我有用,下面提到的第三和第四点都不起作用

  1. 如果我选中标题复选框,则会选中所有子复选框
  2. 如果取消选中,则所有内容都将取消选中
  3. 如果一切都被检查..如果我取消选中一个子复选框...标题复选框将取消选中
  4. 如果我逐个检查所有子复选框....标题复选框将被选中。
  5. 这是我的代码

    <DataGridTemplateColumn>
        <DataGridTemplateColumn.Header>
            <CheckBox Content="Included" x:Name="headerCheckBox" />
        </DataGridTemplateColumn.Header>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <CheckBox Name="chkselectAll" IsChecked="{Binding IsChecked,ElementName=headerCheckBox,Mode=OneWay}"></CheckBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn> 
    
    我可以在这里得到一些帮助吗?我如何在xaml中实现它?

    select all checkbox

    我希望像这样选择所有复选框行为

    https://www.codeproject.com/Articles/42437/Toggling-the-States-of-all-CheckBoxes-Inside-a-Dat#

1 个答案:

答案 0 :(得分:2)

您应该将CheckBox中的CellTemplate绑定到数据对象的source属性:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <CheckBox Name="chkselectAll" IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}"></CheckBox>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

确保数据对象实现INotifyPropertyChanged接口:

public class Item : INotifyPropertyChanged
{
    private bool _isChecked;
    public bool IsChecked
    {
        get { return _isChecked; }
        set { _isChecked = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后,您可以将标头CheckBox的属性绑定到视图模型的属性,只要DataGrid的源集合中的项发生更改,就会设置该属性,例如:

<DataGridTemplateColumn.Header>
    <CheckBox Content="Included"
                x:Name="headerCheckBox"
                IsChecked="{Binding DataContext.AllChecked, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</DataGridTemplateColumn.Header>
public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Items = new ObservableCollection<Item>();
        Items.CollectionChanged += Items_CollectionChanged;

        //add the items..:
        Items.Add(new Item());
        Items.Add(new Item() { IsChecked = true });
        Items.Add(new Item());
    }

    private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (object item in e.NewItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }

        if (e.OldItems != null)
        {
            foreach (object country in e.OldItems)
            {
                (country as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
    }

    private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged("AllChecked");
    }

    public ObservableCollection<Item> Items { get; private set; }

    public bool AllChecked
    {
        get { return Items.All(x => x.IsChecked); }
        set
        {
            foreach (var item in Items)
                item.IsChecked = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}