MVVM模式下如何从ViewModel实现WPF DataGrid全选/取消全选行
实现方案
以下两种方案均完全符合MVVM规范,无需在ViewModel中引用View控件对象,可按需选择:
方案1:绑定DataGridRow的IsSelected属性(推荐,耦合度最低)
该方案无需依赖任何第三方工具,同时可直接支持全选、批量选中功能
- 首先修改行模型
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)); } }
- 修改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>
- 在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:附加属性实现(适合不想修改行模型的场景)
如果不想改动现有行模型,可以通过自定义附加属性实现取消选中的触发逻辑
- 新增附加属性类:
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); } }
- 在XAML中绑定附加属性:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ObCol_View_Parametric}" SelectedItem="{Binding SelectedItem}" local:DataGridExtensions.ClearSelected="{Binding IsClearSelected}"> <!-- 原有逻辑保留 --> </DataGrid>
- 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
相关产品推荐
相关产品推荐

