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

如何基于MVVM模式实现WPF DataGrid的一键全选/取消全选

如何在不破坏MVVM模式的前提下实现WPF DataGrid全选/取消全选

你的现有实现确实违反了MVVM核心原则——ViewModel直接引用了View层的MainWindow和DataGrid控件,导致视图与视图模型高度耦合,难以测试和维护。以下是符合MVVM规范的实现方案:


现有问题代码(不符合MVVM)

XAML部分

<Button Command="{Binding SelButtonClicked}" .../>

ViewModel部分

public RelayCommand SelButtonClicked { get; set; }

public MainViewModel()
{
  SelButtonClicked = new RelayCommand(SelUnsel);
}

public void SelUnsel(object param)
{
    var win = Application.Current.Windows
        .Cast<Window>()
        .FirstOrDefault(window => window is MainWindow) as MainWindow;
    
    if (win.myGrid.SelectedItems.Count > 0)
    {
        win.myGrid.UnselectAll();
    }
    else
    {
        win.myGrid.SelectAll();
    }
}

符合MVVM的实现方案

步骤1:给数据模型添加选中状态属性

让你的数据模型实现INotifyPropertyChanged,新增IsSelected属性来维护选中状态:

public class DataItem : INotifyPropertyChanged
{
    private bool _isSelected;
    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            _isSelected = value;
            OnPropertyChanged(nameof(IsSelected));
        }
    }

    // 你的其他业务属性,例如:
    public string Name { get; set; }
    public int Id { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

步骤2:ViewModel中实现全选逻辑

ViewModel只操作数据集合,不直接接触View控件:

public class MainViewModel : INotifyPropertyChanged
{
    // 绑定到DataGrid的数据源集合
    public ObservableCollection<DataItem> DataItems { get; set; }

    // 全选/取消全选命令
    public RelayCommand ToggleSelectAllCommand { get; set; }

    public MainViewModel()
    {
        DataItems = new ObservableCollection<DataItem>();
        // 初始化测试数据(示例)
        DataItems.Add(new DataItem { Id = 1, Name = "数据项1" });
        DataItems.Add(new DataItem { Id = 2, Name = "数据项2" });

        ToggleSelectAllCommand = new RelayCommand(ToggleSelectAll);
    }

    private void ToggleSelectAll(object param)
    {
        // 判断当前是否有已选中的项
        bool hasSelectedItems = DataItems.Any(item => item.IsSelected);
        // 切换所有项的选中状态
        foreach (var item in DataItems)
        {
            item.IsSelected = !hasSelectedItems;
        }
    }

    // INotifyPropertyChanged实现
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

步骤3:XAML中绑定选中状态

修改DataGrid,添加绑定IsSelected的复选框列,并关联命令:

<DataGrid ItemsSource="{Binding DataItems}" 
          SelectionMode="Extended"
          AutoGenerateColumns="False">
    <DataGrid.Columns>
        <!-- 绑定选中状态的复选框列 -->
        <DataGridCheckBoxColumn Header="选择" 
                                Binding="{Binding IsSelected, Mode=TwoWay}"
                                IsReadOnly="False"/>
        <!-- 你的其他业务列 -->
        <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
        <DataGridTextColumn Header="名称" Binding="{Binding Name}"/>
    </DataGrid.Columns>
</DataGrid>

<!-- 全选/取消全选按钮 -->
<Button Command="{Binding ToggleSelectAllCommand}" Content="全选/取消全选"/>

可选优化:同步DataGrid内置选中状态

如果需要让DataGrid的SelectedItems集合与IsSelected属性完全同步,可以在View的代码后置中添加SelectionChanged事件处理(仅View层逻辑,不影响ViewModel):

private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (sender is DataGrid dataGrid)
    {
        foreach (var item in e.AddedItems)
        {
            if (item is DataItem dataItem)
                dataItem.IsSelected = true;
        }
        foreach (var item in e.RemovedItems)
        {
            if (item is DataItem dataItem)
                dataItem.IsSelected = false;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:20:54