You need to enable JavaScript to run this app. MVVM模式下如何从ViewModel实现WPF DataGrid全选/取消全选行
优惠活动
大模型
产品
解决方案
定价
更多

MVVM模式下如何从ViewModel实现WPF DataGrid全选/取消全选行

实现方案

以下两种方案均完全符合MVVM规范,无需在ViewModel中引用View控件对象,可按需选择:

方案1:绑定DataGridRow的IsSelected属性(推荐,耦合度最低)

该方案无需依赖任何第三方工具,同时可直接支持全选、批量选中功能

  1. 首先修改行模型View_prices_manager<T>,新增IsSelected属性并实现INotifyPropertyChanged接口:
public class View_prices_manager<T> : INotifyPropertyChanged
{
    private bool _isSelected;
    public bool IsSelected
    {
        get => _isSelected;
        set 
        { 
            _isSelected = value;
            OnPropertyChanged();
        }
    }

    // 保留原有Price等其他属性的定义
    public decimal Price { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 修改XAML中的DataGrid,添加行样式绑定IsSelected属性:
<DataGrid AutoGenerateColumns="False"
          ItemsSource="{Binding ObCol_View_Parametric}"
          SelectedItem="{Binding SelectedItem}">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        </Style>
    </DataGrid.RowStyle>
    <!-- 原有Interaction.Triggers逻辑保留 -->
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <GalaCmd:EventToCommand Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>
  1. 在ViewModel的perform方法中,处理完业务逻辑后遍历集合将所有行的IsSelected设为false即可:
public void perform()
{
    foreach (View_prices_manager<T> item in SelectedItems)
    {
        item.Price *= ratio;
    }

    // 取消所有行选中
    foreach (var item in ObCol_View_Parametric)
    {
        item.IsSelected = false;
    }
    SelectedItems = null;
}

如果需要实现全选功能,仅需新增全选命令,遍历集合将所有IsSelected设为true即可。

方案2:附加属性实现(适合不想修改行模型的场景)

如果不想改动现有行模型,可以通过自定义附加属性实现取消选中的触发逻辑

  1. 新增附加属性类:
public static class DataGridExtensions
{
    public static readonly DependencyProperty ClearSelectedProperty = DependencyProperty.RegisterAttached(
        "ClearSelected", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(false, OnClearSelectedChanged));

    private static void OnClearSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is DataGrid dataGrid && (bool)e.NewValue)
        {
            dataGrid.UnselectAll();
            // 重置状态方便下次触发
            SetClearSelected(dataGrid, false);
        }
    }

    public static void SetClearSelected(DependencyObject element, bool value)
    {
        element.SetValue(ClearSelectedProperty, value);
    }

    public static bool GetClearSelected(DependencyObject element)
    {
        return (bool)element.GetValue(ClearSelectedProperty);
    }
}
  1. 在XAML中绑定附加属性:
<DataGrid AutoGenerateColumns="False"
          ItemsSource="{Binding ObCol_View_Parametric}"
          SelectedItem="{Binding SelectedItem}"
          local:DataGridExtensions.ClearSelected="{Binding IsClearSelected}">
    <!-- 原有逻辑保留 -->
</DataGrid>
  1. ViewModel中新增对应的属性,处理完逻辑后触发即可:
// ViewModel需要实现INotifyPropertyChanged接口
private bool _isClearSelected;
public bool IsClearSelected
{
    get => _isClearSelected;
    set 
    { 
        _isClearSelected = value;
        OnPropertyChanged();
    }
}

public void perform()
{
    foreach (View_prices_manager<T> item in SelectedItems)
    {
        item.Price *= ratio;
    }

    // 触发取消全选
    IsClearSelected = true;
    SelectedItems = null;
}

提示:示例代码中你原有XAML绑定的集合属性名为ObCol_View,但ViewModel中暴露的集合属性是ObCol_View_Parametric,需要修正绑定名称保证一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 23:54:03