WPF中DataGrid选中行无法写入SQL表的问题求助
问题排查与解决方法
核心问题分析
- 按钮始终启用:
RelayCommand的CanExecute状态未随SelectedItems的变化而自动更新 - 方法未按预期触发:DataGrid选中项未正确同步到ViewModel的
SelectedItems集合,且数据写入逻辑缺少提交操作
分步解决
1. 修复DataGrid选中项与ViewModel的同步问题
DataGrid的SelectedItems是只读集合,直接绑定无法实现双向同步,可通过以下两种方式解决:
方式一:通过SelectionChanged事件手动同步
在XAML的DataGrid中添加事件绑定:
<DataGrid ItemsSource="{Binding DataGridItems}" SelectionMode="Extended" SelectionChanged="DataGrid_SelectionChanged"/>
在视图后台实现事件处理逻辑:
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { var viewModel = DataContext as DataGridViewModel; viewModel.SelectedItems.Clear(); foreach (var item in (sender as DataGrid).SelectedItems) { viewModel.SelectedItems.Add(item as States); } }
方式二:使用附加属性(MVVM友好方案)
创建附加属性来实现SelectedItems的双向绑定:
public class DataGridSelectionHelper { public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached("SelectedItems", typeof(ObservableCollection<object>), typeof(DataGridSelectionHelper), new PropertyMetadata(null, OnSelectedItemsChanged)); public static ObservableCollection<object> GetSelectedItems(DependencyObject obj) { return (ObservableCollection<object>)obj.GetValue(SelectedItemsProperty); } public static void SetSelectedItems(DependencyObject obj, ObservableCollection<object> value) { obj.SetValue(SelectedItemsProperty, value); } private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is DataGrid dataGrid) { dataGrid.SelectionChanged += (s, args) => { var selectedItems = GetSelectedItems(dataGrid); selectedItems.Clear(); foreach (var item in dataGrid.SelectedItems) { selectedItems.Add(item); } }; } } }
在XAML中引用该附加属性:
<DataGrid ItemsSource="{Binding DataGridItems}" local:DataGridSelectionHelper.SelectedItems="{Binding SelectedItems}"/>
2. 修复RelayCommand的CanExecute状态更新问题
当SelectedItems集合内容变化时,需要主动通知RelayCommand重新评估CanExecute状态:
首先确保你的RelayCommand实现包含触发CanExecuteChanged的方法:
public class RelayCommand : ICommand { private readonly Action<object> _execute; private readonly Func<object, bool> _canExecute; public event EventHandler CanExecuteChanged; public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute == null || _canExecute(parameter); } public void Execute(object parameter) { _execute(parameter); } public void RaiseCanExecuteChanged() { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } }
然后在ViewModel中监听SelectedItems的集合变化,触发命令状态更新:
public DataGridViewModel() { DataGridItems = new ObservableCollection<States>(); SelectedItems = new ObservableCollection<States>(); // 监听集合元素变化事件 SelectedItems.CollectionChanged += SelectedItems_CollectionChanged; LoadDataFromDatabase(); SendSelectedRowsToSQLCommand = new RelayCommand(SendSelectedRowsToSQL, CanSendSelectedRows); } private void SelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { // 通知命令重新评估CanExecute状态 (SendSelectedRowsToSQLCommand as RelayCommand)?.RaiseCanExecuteChanged(); }
3. 修复数据写入SQL的逻辑问题
SendSelectedRowsToSQL方法中缺少SaveChanges()调用,导致数据仅在内存中添加,未提交到数据库:
public void SendSelectedRowsToSQL(object parameter) { using (var context = new DbProjectEntities()) { foreach (var item in SelectedItems) { context.orderedStateTbl.Add(new orderedStateTbl { orderStateId = item.StateID, oStateName = item.StateName }); } // 添加此行提交数据库更改 context.SaveChanges(); } }
验证要点
- 确认DataGrid的
SelectionMode设置为Single或Extended(默认值为Single) - 检查ViewModel的
SelectedItems在选中行时是否正确添加了对应元素 - 测试按钮状态:未选中行时禁用,选中后启用;点击按钮后验证数据是否成功写入SQL表
内容的提问来源于stack exchange,提问作者farzad
相关产品推荐
相关产品推荐

