Если вы посмотрите на трассировку стека в отладчике при вызове 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 Toolkit будет обновлен, он, вероятно, вырастет аналогичная функция, если это не будет исправлено. (И я предполагаю, что если вы используете текущую редакцию - февраль 2010 г., когда я пишу это) - WPF Toolkit и используете свойство ItemBindingGroup
, чтобы явно запросить группу привязки, вы увидите точно такую же проблему. )
Это не объясняет, как вы будете получать вызовы BeginEdit
для случайных объектов, как вы описали. Я не могу это воспроизвести. Но это объясняет двойные вызовы на выбранном объекте. Лучшее, что можно сделать, - это написать исходные объекты, чтобы они допускали двойные вызовы.