Wir sind auf einen seltsamen Fehler gestoßen, bei dem Probleme beim Debuggen auftreten.Warum sollte das Überschreiben von .GetHashCode diese datengebundenen Werte in WinForms löschen?
Wir haben einen MDI-Arbeitsbereich, der Microsoft CAB, DevExpress-Komponenten und .Net 3.5 verwendet.
Wenn Benutzer zwei Fenster im Arbeitsbereich öffnen, die jeweils ein an zwei separate Datenmodelle gebundenes UserControl
enthalten, minimieren Sie beide, das erste zu minimierende Fenster erhält die gebundenen Felder, wenn das zweite minimiert wird. Die Methoden .Equals
und .GetHashCode
des Datenmodells wurden außer Kraft gesetzt, so dass beide Datenmodelle als gleich angesehen werden. Wenn wir das ändern, damit sie einzigartig sind, bekommen wir dieses Verhalten nicht.
Hier ist ein Beispiel Pseudo-Code, das Problem zeigt
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();
Hier ist der Call-Stack, wenn das zweite Fenster minimiert wird:
Am EndEditSession()
Anruf in dem Stack-Trace oben, es ist Rufen EndEditSession
für die Sekunde Fenster minimiert, während zu der Zeit der Stack Trace über die [External Code]
t o der OnChange-Breakpoint, den ich gesetzt habe, wird die Änderungsmethode im ersten-Fenster ausgelöst.
EndEditSession()
ist etwas Brauch wir implementiert haben, die so etwas wie dieses
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
wird bevölkert aussieht, wenn die Usercontrol seine Datenbindungen initialisiert. Die Schlüsselfelder sind der Name des gebundenen Steuerelements und die Wertfelder sind ein benutzerdefiniertes Objekt, das das Steuerelement selbst, seinen Namen, seinen gebundenen Wert und seinen Standardwert speichert. bv.Component
gibt die Steuerung, dass die Bindung an eingestellt wird, die im Fall von meinem Test ist eine maßgeschneiderte DevExpress LookupEdit
_data
enthält das Datenmodell für die UserControl
, und kann überprüfen, dass es zu der Instanz für den zweiten Satz wird Fenster.
Mein ursprünglicher Gedanke war, dass die BindingContext
geteilt wurde, so dass die falsche PropertyManager
zurückgegeben wurde, aber ich habe festgestellt, dass die .BindingContext
für die beiden Formulare und Steuerelemente getrennt sind.
Ist es möglich, dass ein UserControl
zwei getrennte Kopien mit zwei getrennten Instanzen eines Datenmodells gebunden würde seine Bindungen sich einlassen, wenn die GetHashCode
Methode überschrieben worden ist, so dass die beiden Objekte als gleich betrachtet werden?
Ich bin nicht sehr vertraut mit den inneren Funktionen des WinForms-Bindungssystems oder mit genau, wie CAB MDI-Arbeitsbereich verwaltet wird.
Meine Theorie ist, dass, wenn das erste Fenster minimiert, es die Steuerelemente entlädt, Speicher zu sparen, dann, wenn das zweite Fenster minimiert die interne Hash-Tabelle, die die Bindungen verwaltet, wird falsch verwirrt und führt ein Update zum Abrufen von Daten aus das erste minimierte Fenster (das jetzt leer ist) und das Aktualisieren seiner Datenquelle.Es gibt viele Löcher in dieser Theorie, aber es ist das einzige, was ich mir vorstellen kann.
Das war mein erster Gedanke auch, aber das gleiche Problem tritt immer noch auf, wenn Sie jedem Steuerelement zuweisen eigene 'BindingContext' – Rachel
@Rachel Kannst du ein Beispielprojekt zur Verfügung stellen? Es scheint, dass es nicht genug Informationen über Sie Problem gibt. Ich denke, das Problem ist nicht mit BindingContext. Das Problem liegt möglicherweise in Ihrem _bindingValues-Objekt. – nempoBu4
Ich konnte das in einem Beispielprojekt tatsächlich nicht reproduzieren, was ich denke, weil ich in meinem Beispiel keinen vollständigen MDI-Arbeitsbereich mit Smartparts erstellt habe. Der Beispielcode, mit dem ich arbeitete, ist nur ein Formular mit einem TabControl, einem benutzerdefinierten Objekt und einem benutzerdefinierten Benutzersteuerelement mit dem benutzerdefinierten Bindungscode. Ich werde es heute noch einmal versuchen und sehen, ob ich das Problem in einem größeren Beispielprojekt reproduzieren kann. – Rachel