System.ArgumentException al seleccionar filas en WPF DataGrid

En este artículo se proporciona una resolución para resolver lo que ocurre al seleccionar filas en System.ArgumentException controles DataGrid de WPF.

Versión del producto original:   Microsoft .NET Framework 4.5
Número KB original:   2909048

Síntomas

Ha desarrollado una aplicación de Microsoft .NET Framework 4.x que usa el control DataGrid Windows Presentation Foundation (WPF). La propiedad ItemsSource del control DataGrid está enlazada a una colección de objetos personalizados. Después de modificar los valores de una fila en el control DataGrid y seleccionar una fila diferente, recibirá la siguiente excepción y pila de llamadas. Este comportamiento solo se produce al ejecutar la aplicación en un equipo con Microsoft .NET Framework 4.5 o posterior instalado.

System.ArgumentException no se ha controlada
HResult=-2147024809
Message=Ya se ha agregado un elemento con la misma clave.
Source=mscorlib
StackTrace:
en System.ThrowHelper.ThrowArgumentException(recurso ExceptionResource)
en System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add)
en System.Collections.Generic.Dictionary 2..ctor(IDictionary 2 dictionary, IEqualityComparer 1 comparer)
en System. Windows. Controls.Primitives.Selector.InternalSelectedItemsStorage.. ctor(InternalSelectedItemsStorage collection, IEqualityComparer 1 equalityComparer)
en System. Windows. Controls.Primitives.Selector.SelectionChanger.ApplyCanSelectMultiple()
en System. Windows. Controls.Primitives.Selector.SelectionChanger.End()
en System. Windows. Controls.SelectedItemCollection.EndUpdateSelectedItems()
en System. Windows. Controls.Primitives.MultiSelector.EndUpdateSelectedItems()
en System. Windows. Controls.DataGrid.MakeFullRowSelection(ItemInfo info, Boolean allowsExtendSelect, Boolean allowsMinimalSelect)

Causa

El objeto ItemsSource de DataGrid está enlazado a una colección de objetos personalizados, cuya definición de tipo ha invalidado el método Object.GetHashCode. El método invalidado tiene una implementación incorrecta que calcula un hash en función de las propiedades GetHashCode mutables de la clase. Se trata de un error de aplicación, que se expone en Microsoft .NET Framework 4.5 y versiones posteriores. En Microsoft .NET Framework 4.5, la implementación de la clase WPF se cambió para hacer un uso más amplio de HashTables; con el fin de obtener ventajas Selector de rendimiento.

Solución

Modifique la definición de tipo del objeto personalizado para cumplir las directrices de invalidación GetHashCode .

Más información

Si un tipo calcula su hash basándose en propiedades mutables y los valores de una o más de las propiedades mutables cambian; a continuación, el hash calculado devuelto desde su método GetHashCode invalidado también cambia. Si esto ocurre mientras el objeto se almacena en hashTable interno de WPF, ya no se puede recuperar en función del hash original. WPF detecta que el objeto no está disponible en HashTable y lo agrega de nuevo en función del nuevo hash. A continuación, intenta insertar datos Selector relacionados en un diccionario interno con una clave. Sin embargo, se produce una excepción porque un elemento con esa clave ya se había agregado anteriormente al Diccionario.

Solo debe GetHashCode invalidar si:

  • Puede calcular el código hash a partir de campos que no son mutables; o
  • Puede asegurarse de que el código hash de un objeto mutable no cambie mientras el objeto esté contenido en una colección que se base en su código hash.