You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中实现DataGrid复选框全选/全不选功能

实现全选/全不选功能的完整方案

首先得先修正你的WorkStep类——现有代码用了静态事件,这不是WPF数据绑定的标准做法,会导致所有实例共享同一个事件,容易引发意外问题。我们先让它正确实现INotifyPropertyChanged接口:

public class WorkStep : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isChecked;
    public string Name { get; }

    public WorkStep(string name)
    {
        Name = name;
        IsChecked = true;
    }

    public WorkStep(string name, bool isChecked)
    {
        Name = name;
        IsChecked = isChecked;
    }

    public bool IsChecked
    {
        get => isChecked;
        set
        {
            if (isChecked != value)
            {
                isChecked = value;
                OnPropertyChanged(nameof(IsChecked));
            }
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

接下来,假设你有一个管理WorkStep集合的ViewModel(比如MainViewModel),我们要在这个类里添加全选控制逻辑,同时处理集合项的状态联动:

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<WorkStep> _workSteps;
    private bool? _allChecked; // 用可空布尔值支持"部分选中"的不确定状态

    public ObservableCollection<WorkStep> WorkSteps
    {
        get => _workSteps;
        set
        {
            if (_workSteps != value)
            {
                // 移除旧集合的事件监听
                if (_workSteps != null)
                {
                    foreach (var step in _workSteps)
                        step.PropertyChanged -= WorkStep_PropertyChanged;
                }

                _workSteps = value;

                // 给新集合的每个项添加事件监听
                if (_workSteps != null)
                {
                    foreach (var step in _workSteps)
                        step.PropertyChanged += WorkStep_PropertyChanged;
                }

                OnPropertyChanged(nameof(WorkSteps));
                UpdateAllCheckedState();
            }
        }
    }

    public bool? AllChecked
    {
        get => _allChecked;
        set
        {
            if (_allChecked != value)
            {
                _allChecked = value;
                OnPropertyChanged(nameof(AllChecked));
                // 同步更新所有项的选中状态
                if (value.HasValue && WorkSteps != null)
                {
                    foreach (var step in WorkSteps)
                        step.IsChecked = value.Value;
                }
            }
        }
    }

    // 监听单个项的选中状态变化,更新全选框状态
    private void WorkStep_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(WorkStep.IsChecked))
        {
            UpdateAllCheckedState();
        }
    }

    // 根据集合项的状态,计算全选框应该显示的状态
    private void UpdateAllCheckedState()
    {
        if (WorkSteps == null || WorkSteps.Count == 0)
        {
            _allChecked = false;
        }
        else
        {
            var allChecked = WorkSteps.All(s => s.IsChecked);
            var noneChecked = WorkSteps.All(s => !s.IsChecked);

            // 全选→true,全不选→false,部分选→null(对应CheckBox的不确定状态)
            _allChecked = allChecked ? true : noneChecked ? false : null;
        }

        OnPropertyChanged(nameof(AllChecked));
    }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // 示例构造函数,初始化测试数据
    public MainViewModel()
    {
        WorkSteps = new ObservableCollection<WorkStep>
        {
            new WorkStep("需求分析"),
            new WorkStep("原型设计"),
            new WorkStep("开发编码", false),
            new WorkStep("测试验收")
        };
    }
}

最后修改你的XAML代码,在DataGrid的表头添加全选CheckBox,并绑定到ViewModel的AllChecked属性:

<DataGrid ItemsSource="{Binding WorkSteps}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <!-- 表头的全选CheckBox -->
            <DataGridTemplateColumn.HeaderTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding DataContext.AllChecked, 
                                                  RelativeSource={RelativeSource AncestorType=DataGrid}, 
                                                  UpdateSourceTrigger=PropertyChanged}" 
                              HorizontalAlignment="Center"/>
                </DataTemplate>
            </DataGridTemplateColumn.HeaderTemplate>
            <!-- 单元格的单个CheckBox -->
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" 
                              HorizontalAlignment="Center"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <!-- 显示步骤名称的列 -->
        <DataGridTextColumn Header="步骤名称" Binding="{Binding Name}" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

别忘了把ViewModel设置为窗口的DataContext(比如在窗口构造函数里):

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainViewModel();
}

核心逻辑说明:

  • 全选CheckBox支持三种状态:选中(全选所有项)、未选中(取消所有项)、不确定(部分项选中),用户体验更友好。
  • 单个项的选中状态变化会实时同步到全选框;全选框的状态变化也会同步到所有项,实现双向联动。
  • 严格遵循WPF的MVVM模式,数据和UI完全解耦,代码可维护性更强。

内容的提问来源于stack exchange,提问作者Dragan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:20:39