如何将WinForms DataGridView选中行绑定到MVVM ViewModel选中项属性?
WinForms DataGridView 绑定选中项到 ViewModel 的优化方案探讨
自.NET 7起,微软增强了Windows Forms的绑定能力,使其更贴近WPF等XAML技术。但WinForms的DataGridView没有WPF中DataGrid直接绑定ViewModel选中项属性(SelectedItem)的特性,主要限制包括:
DataGridView.SelectedRows是行集合,无法直接绑定单个选中项DataGridView.CurrentRow为只读属性,直接绑定会失败DataGridView.CurrentCell可用于设置当前行,但需要传入DataGridViewCell对象
我曾尝试通过Binding.Format和Parse事件实现绑定,代码如下,但运行时事件会多次触发,导致程序卡顿、按钮失效等异常:
var currentRowBinding = myDataGrid.DataBindings.Add("CurrentCell", mViewModel.Items, nameof(mViewModel.CurrentItem), true); // Binding.Format事件在数据源值变更、需要显示到控件前触发,用于格式化值 currentRowBinding.Format += CurrentRowBinding_Format; // Binding.Parse事件在控件值变更、需要更新到数据源前触发,用于解析/转换值 currentRowBinding.Parse += CurrentRowBinding_Parse; private void CurrentRowBinding_Format(object? sender, ConvertEventArgs e) { var itemIndex = mViewModel.Items.IndexOf(mViewModel.CurrentItem); e.Value = myDataGrid[0, itemIndex]; myDataGrid.Rows[itemIndex].Selected = true; } private void CurrentRowBinding_Parse(object? sender, ConvertEventArgs e) { e.Value = myDataGrid.CurrentRow.DataBoundItem; }
目前我的解决方案是通过监听BindingSource.CurrencyManager.CurrentChanged事件同步ViewModel的CurrentItem与网格选中行,同时在ViewModel中定义CurrentItemChanged事件,同步ViewModel侧的修改到网格,代码如下:
private void CurrencyManager_CurrentChanged(object? sender, EventArgs e) { if (mCurrencyManager.Current != mViewModel.CurrentItem) { mViewModel.CurrentItem = mCurrencyManager.Current as TViewModel; } } private void ViewModel_CurrentItemChanged(object? sender, EventArgs e) { if (mViewModel.CurrentItem != mCurrencyManager.Current) { var itemIndex = mViewModel.Items.IndexOf(mViewModel.CurrentItem); mCurrencyManager.Position = itemIndex; } }
请问是否有更优的实现方案?
内容的提问来源于stack exchange,提问作者Pedro Gaspar
相关产品推荐
相关产品推荐

