WPF MVVM模式下如何获取DataGrid按钮所在行的列值?
在WPF MVVM模式下获取DataGrid行按钮对应的行数据
要在MVVM模式下实现需求,核心是通过命令绑定替代传统的Click事件,并直接传递行数据对象,避免依赖UI元素。以下是具体实现步骤:
1. 修改XAML,绑定命令与行数据
把按钮的Click事件替换为Command绑定,同时将当前行的实体对象作为CommandParameter传递给ViewModel:
<DataGrid Name="NestCards" FontSize="12" ScrollViewer.CanContentScroll="True" MaxHeight="400" ColumnWidth="*" ItemsSource="{Binding NestItems}"> <!-- 绑定ViewModel中的数据集合 --> <DataGrid.Columns> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="Details" <!-- 绑定到ViewModel中的命令 --> Command="{Binding DataContext.GetDetailsCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" <!-- 传递当前行的实体对象 --> CommandParameter="{Binding}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
注:
RelativeSource用于定位到DataGrid的DataContext(即ViewModel),确保命令绑定正确。
2. 实现命令基类(若未使用MVVM框架)
如果没有用Prism、MVVM Light等框架,先实现一个简单的RelayCommand用于绑定:
public class RelayCommand<T> : ICommand { private readonly Action<T> _execute; private readonly Func<T, bool> _canExecute; public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public bool CanExecute(object parameter) => _canExecute?.Invoke((T)parameter) ?? true; public void Execute(object parameter) => _execute((T)parameter); public event EventHandler CanExecuteChanged { add => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value; } }
3. 编写ViewModel逻辑
ViewModel需要包含数据集合、命令、UI绑定属性,并实现INotifyPropertyChanged通知UI更新:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; public class MainViewModel : INotifyPropertyChanged { // DataGrid的数据源,绑定SQL查询结果 public ObservableCollection<NestItem> NestItems { get; set; } = new ObservableCollection<NestItem>(); // 处理详情按钮的命令 public ICommand GetDetailsCommand { get; } // 绑定UI显示的属性 private string _nestStatus; public string NestStatus { get => _nestStatus; set { _nestStatus = value; OnPropertyChanged(); } } private string _nestName; public string NestName { get => _nestName; set { _nestName = value; OnPropertyChanged(); } } private string _schedFor; public string SchedFor { get => _schedFor; set { _schedFor = value; OnPropertyChanged(); } } public MainViewModel() { GetDetailsCommand = new RelayCommand<NestItem>(ExecuteGetDetails); // 这里初始化NestItems,比如从SQL查询加载数据 // LoadNestItemsFromSql(); } private void ExecuteGetDetails(NestItem selectedItem) { if (selectedItem == null) return; // 直接获取行数据的属性,无需反射 NestStatus = selectedItem.OrderStatus; NestName = selectedItem.NestName; SchedFor = selectedItem.DueDate.ToString(); // 用selectedItem.NestName执行你的SQL查询 // var details = YourSqlQueryMethod(selectedItem.NestName); } // 属性变更通知实现 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
4. 定义实体类对应SQL数据
创建与SQL查询结果匹配的实体类,强类型处理数据:
public class NestItem { public string NestName { get; set; } public DateTime DueDate { get; set; } public string OrderStatus { get; set; } // 其他对应SQL字段的属性 }
5. 设置View的DataContext
在窗口或页面的构造函数中,将DataContext绑定到ViewModel:
public MainWindow() { InitializeComponent(); DataContext = new MainViewModel(); }
核心优势
- 完全符合MVVM分离原则,UI与业务逻辑解耦
- 强类型获取行数据,避免反射的低效与不安全
- 命令绑定更易于测试和维护
内容的提问来源于stack exchange,提问作者user32602103
相关产品推荐
相关产品推荐

