WPF DataGrid:处理CanUserAddRows =真正干净利用MVVM

WPF DataGrid:处理CanUserAddRows =真正干净利用MVVM

问题描述:

我最近一直在研究MVVM,并且在发现Caliburn.Micro之后,事情已经非常激烈;我还处于早期学习阶段,但我相信我对MVVM基础知识有一个好的感觉。WPF DataGrid:处理CanUserAddRows =真正干净利用MVVM

我碰到的问题与WPF DataGrid,虽然 - 这是相当多,我曾与WinForms的DataGridViewsame issues:如何赫克你处理CanUserAddRows=true在电网项目加入干净?

我显然不想DataGrid特异性黑客添加到我的视图模型,因为它理想应该是多用途其他View控制。同时,我希望能够在添加新的 项目时获得通知,以便我可以立即坚持下去。

我将DataGrid绑定为BindableCollection<FooModel> FooItems - 使用干净的MVVM设计,如果我理解正确,我将能够处理FooItems.CollectionChanged并对添加/删除事件做出反应。但是,DataGrid只要添加了默认构造的项目就会触发Add事件 - 这显然是而不是是保持对象的正确时间!

经过大量的谷歌搜索和*挖掘,我得到的印象是DataGrid完全迟缓在如何发射添加/删除事件。与CanUserAddRows=true一起使用它的人似乎只能在内存中收集,其中持有数据的人似乎使用单独的输入字段+ 按钮 用于添加新项目的命令。

FooModel工具INotifyPropertyChanged但不IEditableObject - 据我可以告诉大家,不应该成为问题,不过,因为IEO似乎与属性编辑/撤消,而我的问题是,当添加事件被触发用。 ..

那么,你怎么办来处理并网编辑干净

+1

另一个选择是让FooModel实现IEditableObject。当新项目的编辑操作完成时(例如用户点击输入),DataGrid将调用IEditableObject.EndEdit()。然后,您可以在FooModel上引发一个事件,如EditCommitted。此事件的处理程序可以正确保存新的FooModel实例,或更新现有的实例。 – eulerfx 2010-12-21 00:31:47

+0

@eulerfx:谢谢 - 出于某种原因,我已经排除了IEO,但我不记得为什么;可能会在之前的项目中遇到一些问题。我会再次看看:) – snemarch 2010-12-21 19:48:32

+0

IMO没有干净的方式来实现一个DataGrid中的CanUserAddRows = True。我们已经移动到像上面提到的那样分离输入字段或者编辑Windows的自定义.ShowDialog。批量保存不适合我们的设计。 – knockando 2012-02-17 15:02:10

听起来WPF DataGrid的行为方式与WinForms DataGridView非常相似,因为只要用户开始进入“新行”,它就会在数据源中创建一个项目。后续编辑会导致集合中新项目的属性发生更改。

如果你使用BindingList<FooModel>相反,你会得到额外的事件称为ListChanged - 提供您的FooModel类型实现INotifyPropertyChanged,该事件将触发时,该项目的性质被改变(以及从加入项目时/移除集合)。

希望这会有所帮助!

+0

P.S.如果您使用的是持久数据源,那么在用户完成添加/编辑所有行之后再等待数据源执行单个事务更新会更有意义吗?对持久数据的实时更新看起来很浪费...... – 2010-11-05 14:11:46

+0

是的,就我所知,它们的行为是一样的 - 恕我直言,这是相当迟钝的行为。 BindingList没有什么帮助,不幸的是...它的ItemRemoved几乎是无用的,因为你已经*已经*删除的项目的索引> _ snemarch 2010-11-05 18:52:04

+0

是的,通常情况下,批量提交更改更加安全,它只是没有在我正在做的系统中自然适合。绑定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(); 
    } 
}