繁体   English   中英

如何通过WPF DataGrid中的DataGrid Header CheckBox选择列的所有CheckBox

[英]How to Select All CheckBox of a Column by DataGrid Header CheckBox in WPF DataGrid

我有一个带有一个 CheckBoxColumn 的 DataGrid。 在 CheckBoxColumn 的标题中,我添加了一个 CheckBox 来选择该 Datagrid 行的所有复选框。

我怎样才能做到这一点?

我的 WPF 数据网格 XAML 代码:

    <DataGrid AutoGenerateColumns="False" CanUserAddRows="False"  Grid.RowSpan="2" Height="130" HorizontalAlignment="Left" IsReadOnly="False" Margin="189,340,0,0" Name="dgCandidate" TabIndex="7" VerticalAlignment="Top" Width="466" Grid.Row="1" >
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="colCandidateID" Binding="{Binding CandidateID}" Header="SlNo" MinWidth="20" IsReadOnly="True" />
            <DataGridTextColumn x:Name="colRegistraion" Binding="{Binding RegisterNo}" Header="Reg. No." IsReadOnly="True"  />
            <DataGridTextColumn x:Name="colCandidate" Binding="{Binding CandidateName}" Header="Name" MinWidth="250" IsReadOnly="True"  />

            <DataGridTemplateColumn>
                <DataGridTemplateColumn.Header>
                    <CheckBox Name="chkSelectAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked"></CheckBox>
                </DataGridTemplateColumn.Header>
                <DataGridTemplateColumn.CellTemplate >
                    <DataTemplate >
                        <CheckBox x:Name="colchkSelect1" Checked="colchkSelect1_Checked" Unchecked="colchkSelect1_Unchecked" ></CheckBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

        </DataGrid.Columns>

    </DataGrid>

将你的 Candidate 类转换成这样:

public class Candidate : DependencyObject
{
    //CandidateID Dependency Property
    public int CandidateID
    {
        get { return (int)GetValue(CandidateIDProperty); }
        set { SetValue(CandidateIDProperty, value); }
    }
    public static readonly DependencyProperty CandidateIDProperty =
        DependencyProperty.Register("CandidateID", typeof(int), typeof(Candidate), new UIPropertyMetadata(0));
    //RegisterNo Dependency Property
    public int RegisterNo
    {
        get { return (int)GetValue(RegisterNoProperty); }
        set { SetValue(RegisterNoProperty, value); }
    }
    public static readonly DependencyProperty RegisterNoProperty =
        DependencyProperty.Register("RegisterNo", typeof(int), typeof(Candidate), new UIPropertyMetadata(0));
    //CandidateName Dependency Property
    public string CandidateName
    {
        get { return (string)GetValue(CandidateNameProperty); }
        set { SetValue(CandidateNameProperty, value); }
    }
    public static readonly DependencyProperty CandidateNameProperty =
        DependencyProperty.Register("CandidateName", typeof(string), typeof(Candidate), new UIPropertyMetadata(""));
    //BooleanFlag Dependency Property
    public bool BooleanFlag
    {
        get { return (bool)GetValue(BooleanFlagProperty); }
        set { SetValue(BooleanFlagProperty, value); }
    }
    public static readonly DependencyProperty BooleanFlagProperty =
        DependencyProperty.Register("BooleanFlag", typeof(bool), typeof(Candidate), new UIPropertyMetadata(false));
}

在 MainWindow.xaml 中:

<DataGrid ItemsSource="{Binding CandidateList}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Id" Binding="{Binding CandidateID}"/>
        <DataGridTextColumn Header="RegNr" Binding="{Binding RegisterNo}"/>
        <DataGridTextColumn Header="Name" Binding="{Binding CandidateName}"/>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.Header>
                <CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Checked"></CheckBox>
            </DataGridTemplateColumn.Header>
            <DataGridTemplateColumn.CellTemplate >
                <DataTemplate>
                    <CheckBox IsChecked="{Binding BooleanFlag}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

在 MainWindow.xaml.cs 中:

    public MainWindow()
    {
        DataContext = this;
        CandidateList.Add(new Candidate()
        {
            CandidateID = 1,
            CandidateName = "Jack",
            RegisterNo = 123,
            BooleanFlag = true
        });
        CandidateList.Add(new Candidate()
        {
            CandidateID = 2,
            CandidateName = "Jim",
            RegisterNo = 234,
            BooleanFlag = false
        });
        InitializeComponent();
    }
    //List Observable Collection
    private ObservableCollection<Candidate> _candidateList = new ObservableCollection<Candidate>();
    public ObservableCollection<Candidate> CandidateList { get { return _candidateList; } }
    private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {
        foreach (var item in CandidateList)
        {
            item.BooleanFlag = true;
        }
    }
    private void UnheckBox_Checked(object sender, RoutedEventArgs e)
    {
        foreach (var item in CandidateList)
        {
            item.BooleanFlag = false;
        }
    }

严格来说,模型不应该知道视图,因此,blinmeis 提出的解决方案,其中模型更改是更新数据网格中的每一行,打破了 MVVM/演示设计模式。 请记住,在 MVVM 中,依赖流是视图 -> 视图模型 -> 模型,因此如果您在视图模型(或控件代码隐藏)中引用控件,那么您已经有效地打破了模式,并且可能会进一步遇到问题。

我添加了 CheckBox 以选择 Datagrid Row 中的所有 CheckBox

如果您的意思是选择 datagrid列中的所有复选框,那么我会说:只需使用选中/未选中状态更新您的 itemssource 集合。

public bool SelectAll
{
  get{return this._selectAll;}
  set
  {
     this._selectAll = value;
     this.MyItemsSourceCollection.ForEach(x=>x.MyRowCheckProperty=value);
     this.OnPropertyChanged("SelectAll");
  }
}

xml

        <DataGridTemplateColumn>
            <DataGridTemplateColumn.Header>
                <CheckBox isChecked="{Binding SelectAll}"></CheckBox>
            </DataGridTemplateColumn.Header>
            <DataGridTemplateColumn.CellTemplate >
                <DataTemplate >
                    <CheckBox IsChecked="{Binding MyRowCheckProperty}"></CheckBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

我不知道 xaml 绑定是否正确,但我希望你能看到我的意图

事实证明,要做到这一点比人们希望的要困难得多。

第一个问题是你不能仅仅将视图模型绑定到列标题,因为它没有视图模型作为它的数据上下文,所以你需要一个绑定代理来正确地将绑定路由到视图模型。

public class BindingProxy : Freezable
{
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
        "Data", 
        typeof(object), 
        typeof(BindingProxy),
        new UIPropertyMetadata(null));

    public object Data
    {
        get { return this.GetValue(DataProperty); }
        set { this.SetValue(DataProperty, value); }
    }

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }
}

现在在数据网格的资源中创建一个绑定代理:

<DataGrid.Resources>
    <aon:BindingProxy
        x:Key="DataContextProxy"
        Data="{Binding}" />
</DataGrid.Resources>

然后需要将列定义为:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.HeaderTemplate>
        <DataTemplate>
            <CheckBox
                Command="{Binding
                    Data.SelectAllCommand,
                    Source={StaticResource DataContextProxy}}"
                IsChecked="{Binding
                    Data.AreAllSelected,
                    Mode=OneWay,
                    Source={StaticResource DataContextProxy},
                    UpdateSourceTrigger=PropertyChanged}"
                IsThreeState="True" />
        </DataTemplate>
    </DataGridTemplateColumn.HeaderTemplate>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox
                IsChecked="{Binding
                    Path=IsSelected,
                    UpdateSourceTrigger=PropertyChanged}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

请注意,需要绑定到复选框的IsChecked依赖项属性及其Command属性,并且IsChecked绑定是OneWay IsChecked绑定获取复选框以显示项目的当前状态,而Command绑定执行批量选择。 你需要两者。

现在在视图模型中:

public bool? AreAllSelected
{
    get
    {
        return this.Items.All(candidate => candidate.IsSelected)
        ? true
        : this.Items.All(candidate => !candidate.IsSelected)
            ? (bool?)false
            : null;
    }

    set
    {
        if (value != null)
        {
            foreach (var item in this.Items)
            {
                item.IsSelected = value.Value;
            }
        }

        this.RaisePropertyChanged();
    }
}

SelectAllCommand属性是ICommand一个实现,其中Execute方法是:

public void Execute(object parameter)
{
    var allSelected = this.AreAllSelected;

    switch (allSelected)
    {
        case true:
            this.AreAllSelected = false;
            break;
        case false:
        case null:
            this.AreAllSelected = true;
            break;
    }
}

最后,每次IsSelected的值更改时,您的行项目视图模型(即Items )需要在主视图模型上引发PropertyChanged 你如何做到这一点完全取决于你。

Xaml文件

<DataGrid Grid.Row="1" AutoGenerateColumns="False" ColumnWidth="auto" ItemsSource="{Binding DataPoints}">
                    <DataGrid.Columns>
                        <DataGridCheckBoxColumn Binding="{Binding IsEnable, UpdateSourceTrigger=PropertyChanged}">
                            <DataGridCheckBoxColumn.Header>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Margin="2">启用</TextBlock>
                                    <CheckBox IsChecked="{Binding Data.SelectAll,Source={StaticResource EquipmentPointConfigBindingProxy}}" />
                                </StackPanel>

                            </DataGridCheckBoxColumn.Header>
                        </DataGridCheckBoxColumn>
     </DataGrid.Columns>
     </DataGrid>

.cs文件

  public class BindingProxy : Freezable
    {
        #region Overrides of Freezable

        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        #endregion

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
    }

.cs业务

public ObservableCollection<EquipmentDataPointViewModel> DataPoints { get; set; }


        private bool selectAll;

        public bool SelectAll
        {
            get { return selectAll; }
            set
            {
                selectAll = value;
                foreach (var item in DataPoints)
                {
                    item.IsEnable = value;
                }
                this.RaisePropertyChanged("SelectAll");
            }
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM