Мы столкнулись с странной ошибкой, с которой у нас возникают проблемы с отладкой.
У нас есть рабочее пространство MDI, которое использует компоненты Microsoft CAB, DevExpress и .Net 3.5.
Если пользователи открывают два окна в рабочей области, каждая из которых содержит UserControl
, привязанную к двум отдельным моделям данных, а затем минимизирует их оба, первое окно для минимизации - это очищение связанных полей, когда второй минимизирует.
Методы .Equals
и .GetHashCode
модели данных были переопределены, так что обе модели данных считаются равными. Если мы изменим это так, чтобы они были уникальными, мы не получим такого поведения.
Вот пример псевдокода, показывающий проблему
var a = new MyWindow();
a.DataModel = new SomeClass(123);
a.ShowInMdiWorkspace();
var b = new MyWindow();
b.DataModel = new SomeClass(123);
b.ShowInMdiWorksace();
a.Minimize();
// If SomeClass.GetHashCode() is overwritten to consider two objects
// as equal based on the value passed in, then the data bindings for A
// get cleared on this call. If SomeClass.GetHashCode is unique, then
// this problem does not happen.
b.Minimize();
Здесь стек вызовов при сверке второго окна:
При вызове EndEditSession()
в трассировке стека выше он вызывает EndEditSession
для минимизации второго окна, а к тому времени, когда трассировка стека пройдет мимо [External Code]
до точки останова OnChange, которую я установил, это запуск метода изменения в первом окне.
EndEditSession()
- это то, что мы внедрили, что выглядит примерно так.
protected void EndEditSession()
{
IBindingValue bv = null;
if (_bindingValues == null)
return;
if (_data != null)
{
foreach (KeyValuePair<string, IBindingValue> kvp in _bindingValues)
{
bv = kvp.Value;
if (bv.IsBindable)
((PropertyManager)bv.Component.BindingContext[_data]).EndCurrentEdit();
}
}
}
_bindingValues
заполняется, когда UserControl инициализирует привязки данных. Ключевыми полями являются имя связанного элемента управления, а поля значений - это пользовательский объект, который хранит сам элемент управления, его имя, его значение привязки и значение по умолчанию. bv.Component
возвращает элемент управления, на который установлено привязку, которое в случае моего тестирования является настроенным DevExpress LookupEdit
_data
содержит модель данных для UserControl
, и я могу проверить, что она установлена для экземпляра для второго окна.
Моя первоначальная мысль заключалась в том, что BindingContext
был разделен, поэтому возвращался неправильный PropertyManager
, однако я подтвердил, что .BindingContext
для двух форм и элементов управления является отдельным.
Возможно ли, что наличие двух отдельных копий a UserControl
, привязанных к двум отдельным экземплярам модели данных, приведет к смешению своих привязок, когда метод GetHashCode
был переопределен, так что эти два объекта считаются равными?
Я не очень хорошо знаком с внутренней работой системы привязки WinForms или с тем, как управляется рабочее пространство CAB MDI.
Моя теория заключается в том, что когда первое окно минимизирует, оно выгружает элементы управления для сохранения в памяти, а затем, когда второе окно сводит к минимуму внутреннюю хеш-таблицу, которая управляет привязками, неправильно путает и запускает обновление, чтобы принимать данные из сначала свернутое окно (которое теперь пусто) и обновление его источника данных. В этой теории много дыр, однако это единственное, о чем я могу думать.