System.ArgumentException beim Auswählen von Zeilen in WPF DataGrid

Dieser Artikel enthält eine Lösung zum Auflösen des System.ArgumentException Problems, das auftritt, wenn Sie Zeilen in WPF DataGrid-Steuerelementen auswählen.

Ursprüngliche Produktversion:   Microsoft .NET Framework 4.5
Ursprüngliche KB-Nummer:   2909048

Problembeschreibung

Sie haben eine Microsoft .NET Framework 4.x-Anwendung entwickelt, die das Windows Presentation Foundation (WPF)-DataGrid-Steuerelement verwendet. Die ItemsSource-Eigenschaft des DataGrid-Steuerelements ist an eine Auflistung benutzerdefinierter Objekte gebunden. Nachdem Sie werte für eine Zeile im DataGrid-Steuerelement geändert und eine andere Zeile ausgewählt haben, erhalten Sie die folgende Ausnahme und callstack. Dieses Verhalten tritt nur auf, wenn die Anwendung auf einem Computer ausgeführt wird, auf dem Microsoft .NET Framework 4.5 oder höher installiert ist.

System.ArgumentException wurde nicht behandelt
HResult=-2147024809
Message=Ein Element mit demselben Schlüssel wurde bereits hinzugefügt.
Source=mscorlib
Stacktrace:
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary 2..ctor(IDictionary 2 dictionary, I DictionaryComparer 1 comparer)
bei System. Windows. Controls.Primitives.Selector.InternalSelectedItemsStorage.. ctor(InternalSelectedItemsStorage-Auflistung, ISelectComparer 1 gleichheitComparer)
bei System. Windows. Controls.Primitives.Selector.SelectionChanger.ApplyCanSelectMultiple()
bei System. Windows. Controls.Primitives.Selector.SelectionChanger.End()
bei System. Windows. Controls.SelectedItemCollection.EndUpdateSelectedItems()
bei System. Windows. Controls.Primitives.MultiSelector.EndUpdateSelectedItems()
bei System. Windows. Controls.DataGrid.MakeFullRowSelection(ItemInfo info, Boolean allowsExtendSelect, Boolean allowsMinimalSelect)

Ursache

The DataGrid's ItemsSource is bound to a collection of custom objects, whose type definition has overridden the Object.GetHashCode method. Die überschriebene GetHashCode Methode weist eine falsche Implementierung auf, die einen Hash basierend auf änderbaren Eigenschaften in der Klasse berechnet. Dies ist ein Anwendungsfehler, der in Microsoft .NET Framework 4.5 und höher verfügbar gemacht wird. In Microsoft .NET Framework 4.5 wurde die Implementierung für die Selector WPF-Klasse geändert, um HashTables umfassender zu verwenden, um Leistungsvorteile zu erzielen.

Lösung

Ändern Sie die Typdefinition des benutzerdefinierten Objekts so, dass sie den Richtlinien zum Überschreiben GetHashCode entspricht.

Weitere Informationen

Wenn ein Typ seinen Hash berechnet, indem er änderbare Eigenschaften verwendet, und sich die Werte einer oder mehrerer der änderbaren Eigenschaften ändern; dann ändert sich auch der von der überschriebenen Methode zurückgegebene berechnete GetHashCode Hash. Wenn dies während der Speicherung des Objekts in der internen HashTable von WPF erfolgt, kann es basierend auf dem ursprünglichen Hash nicht mehr abgerufen werden. WPF erkennt, dass das Objekt in der HashTable nicht verfügbar ist, und fügt es basierend auf dem neuen Hash erneut hinzu. Anschließend wird versucht, verwandte Selector Daten mithilfe eines Schlüssels in ein internes Wörterbuch einzufügen. Eine Ausnahme tritt jedoch auf, da ein Element mit diesem Schlüssel bereits zuvor zum Wörterbuch hinzugefügt wurde.

Sie sollten nur dann außer Kraft GetHashCode setzen, wenn:

  • Sie können den Hashcode aus Feldern berechnen, die nicht änderbar sind. Oder
  • Sie können sicherstellen, dass sich der Hashcode eines änderbaren Objekts nicht ändert, während das Objekt in einer Auflistung enthalten ist, die auf seinem Hashcode basiert.