WPF DataGrid:处理CanUserAddRows =真正干净利用MVVM
我最近一直在研究MVVM,并且在发现Caliburn.Micro之后,事情已经非常激烈;我还处于早期学习阶段,但我相信我对MVVM基础知识有一个好的感觉。WPF DataGrid:处理CanUserAddRows =真正干净利用MVVM
我碰到的问题与WPF DataGrid
,虽然 - 这是相当多,我曾与WinForms的DataGridView
的same issues:如何赫克你处理CanUserAddRows=true
在电网项目加入干净?
我显然不想DataGrid
特异性黑客添加到我的视图模型,因为它理想应该是多用途其他View
控制。同时,我希望能够在添加新的
行
项目时获得通知,以便我可以立即坚持下去。
我将DataGrid
绑定为BindableCollection<FooModel> FooItems
- 使用干净的MVVM设计,如果我理解正确,我将能够处理FooItems.CollectionChanged
并对添加/删除事件做出反应。但是,DataGrid
只要添加了默认构造的项目就会触发Add事件 - 这显然是而不是是保持对象的正确时间!
经过大量的谷歌搜索和*挖掘,我得到的印象是DataGrid
完全迟缓在如何发射添加/删除事件。与CanUserAddRows=true
一起使用它的人似乎只能在内存中收集,其中持有数据的人似乎使用单独的输入字段+
按钮
用于添加新项目的命令。
我FooModel
工具INotifyPropertyChanged
但不IEditableObject
- 据我可以告诉大家,不应该成为问题,不过,因为IEO似乎与属性编辑/撤消,而我的问题是,当添加事件被触发用。 ..
那么,你怎么办来处理并网编辑干净?
听起来WPF DataGrid
的行为方式与WinForms DataGridView
非常相似,因为只要用户开始进入“新行”,它就会在数据源中创建一个项目。后续编辑会导致集合中新项目的属性发生更改。
如果你使用BindingList<FooModel>
相反,你会得到额外的事件称为ListChanged
- 提供您的FooModel
类型实现INotifyPropertyChanged
,该事件将触发时,该项目的性质被改变(以及从加入项目时/移除集合)。
希望这会有所帮助!
P.S.如果您使用的是持久数据源,那么在用户完成添加/编辑所有行之后再等待数据源执行单个事务更新会更有意义吗?对持久数据的实时更新看起来很浪费...... – 2010-11-05 14:11:46
是的,就我所知,它们的行为是一样的 - 恕我直言,这是相当迟钝的行为。 BindingList没有什么帮助,不幸的是...它的ItemRemoved几乎是无用的,因为你已经*已经*删除的项目的索引> _ snemarch 2010-11-05 18:52:04
是的,通常情况下,批量提交更改更加安全,它只是没有在我正在做的系统中自然适合。绑定DataTable并能够接受/拒绝ChangeChanges可能是你应该使用的DataGrid :) – snemarch 2010-11-05 18:57:16
我知道这是很长的时间,因为这是问,但我现在正在做类似的事情,并认为我会发布我的解决方案。您可能认为这是一种黑客攻击,但这是我可以通过DataGrid在脱离编辑模式时告诉我的最佳方式(出于我自己的原因)。
我看了一下DataGrid的代码,发现最接近结束编辑我可以覆盖,结果是OnExecutedCommitEdit()。然后我在那个函数结束之后提出一个事件。当我的事件订阅者被调用时,DataGrid不再处于编辑模式,我可以根据需要做任何事情。这里是代码:
/// <summary>
/// Deriving a new DataGrid because we need an event to tell us when editing is complete.
/// </summary>
public class DataGridMod : DataGrid
{
public delegate void EditCompletedDelegate();
public EditCompletedDelegate EditCompleted;
public DataGridMod() { }
protected override void OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
{
base.OnExecutedCommitEdit(e);
if (EditCompleted != null)
EditCompleted();
}
}
另一个选择是让FooModel实现IEditableObject。当新项目的编辑操作完成时(例如用户点击输入),DataGrid将调用IEditableObject.EndEdit()。然后,您可以在FooModel上引发一个事件,如EditCommitted。此事件的处理程序可以正确保存新的FooModel实例,或更新现有的实例。 – eulerfx 2010-12-21 00:31:47
@eulerfx:谢谢 - 出于某种原因,我已经排除了IEO,但我不记得为什么;可能会在之前的项目中遇到一些问题。我会再次看看:) – snemarch 2010-12-21 19:48:32
IMO没有干净的方式来实现一个DataGrid中的CanUserAddRows = True。我们已经移动到像上面提到的那样分离输入字段或者编辑Windows的自定义.ShowDialog。批量保存不适合我们的设计。 – knockando 2012-02-17 15:02:10