我有一个DataGrid绑定到IEditableObject的集合。
现在,当我在单元格中单击两次时,它将被打开以进行编辑。
有趣的是:BeginEdit将被调用两次。有时对于相同的EditableObject,但有时对于两个不同的对象(特别是当我使用PgDn直到我到达DataGrid的末尾)时,将首先调用正确的一个,然后从集合中调用其他一些项目,之前从未进行过聚焦
EndEdit也会被调用两次,但总是针对所选项目,而不是错误的。
这是一个已知问题吗?任何解决方法只能获得(右侧)一个通知。
答案 0 :(得分:20)
如果你看一下,当BeginEdit
被称为调试器堆栈跟踪,你会发现第一次,这是称之为集合视图,而第二次,这是一个BindingGroup
问题似乎是有两件事都认为他们负责IEditableObject
州。当WPF提供了默认的集合视图,它会寻找IEditableObject
在集合中的对象,并调用BeginEdit
,要么EndEdit
或CancelEdit
响应调用相应的IEditableCollectionView
方法。此外,BindingGroup
会调用IEditableObject
方法来响应对BeginEdit
和CommitEdit
或CancelEdit
的调用。
DataGrid
使用这两项功能:当您开始连续完成编辑时,它会通知IEditableCollectionView
和 BindingGroup
以及这两项内容认为他们有责任继续并通知基础源对象的IEditableObject
实现。
所以它看起来像DataGrid
中的一个错误 - 它会导致两个不同的对象调用BeginEdit
(以及相关的方法)。而这是因为它使用的编辑收集意见,并结合集团 - 从它的外观,那些没有被设计在同一时间对同一对象使用,在该DataGrid
使用它们的方式。
你没有看到Toolkit中的网格出现这个问题的原因是它似乎是一个稍微旧的版本 - 将其中的代码与Reflector对.NET 4.0的显示进行比较,你会看到它。 NET 4.0 DataGrid
有一些额外的代码(一种新方法EnsureItemBindingGroup
,以及MeasureOverride
和OnRowValidationRulesChanged
中的一些相关代码),可确保绑定组始终存在,无论您是请问与否。因此,如果更新了WPF工具包,除非得到修复,否则它可能会增加类似的功能。 (我猜想,如果使用当前版本 - 2010年2月,我写这 - WPF工具包,并使用ItemBindingGroup
属性,明确要求结合基团,你会看到完全一样的问题)。
这并没有解释如何按照您的描述在随机对象上调用BeginEdit
。我无法重复这一点。但它确实解释了对所选对象的双重调用。最好的办法似乎是对源对象进行编码,以便它们能够容忍双重调用。
答案 1 :(得分:4)
我不确定在发生之前你用它来中断BeginEdit事件,但是对于EndEdit,一个简单的isDirty标记就可以了。在实现IEditableObject的Entity类中,添加以下内容:
private bool _isDirty = false;
#region IEditableObject Members
public void BeginEdit()
{
// Bug Fix: Windows Controls call EndEdit twice; Once
// from IEditableCollectionView, and once from BindingGroup.
// This makes sure it only happens once after a BeginEdit.
_isDirty = true;
}
public void CancelEdit() { }
public void EndEdit()
{
if (ItemEndEdit != null && _isDirty)
{
_isDirty = false;
ItemEndEdit(this);
}
}
#endregion
答案 2 :(得分:3)
使用.NET Framework 4 DataGrid时遇到同样的问题。
添加对WPFToolkit上一版本的引用
添加
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
并使用<DataGrid>
<dg:DataGrid>
答案 3 :(得分:1)
+1 @IanGriffiths用于解决问题。至于解决方案(或替代方法),您可以计算&#34;待定&#34;编辑。这意味着:
void BeginEdit()
{
_numEdits++;
}
void CancelEdit()
{
if(--_numEdits < 0)
throw new Exception("WTF?");
}
void EndEdit()
{
CancelEdit();
if(_numEdits == 0)
commitEdit();
}