Clase de Diccionario Observable General para DataBinding / WPF C #

Intento crear una Clase de Diccionario Observable para WPF DataBinding en C #. Encontré un buen ejemplo de Andy aquí: enlace de datos bidireccional con un diccionario en WPF

De acuerdo con eso, traté de cambiar el código a lo siguiente:

class ObservableDictionary : ViewModelBase { public ObservableDictionary(Dictionary dictionary) { _data = dictionary; } private Dictionary _data; public Dictionary Data { get { return this._data; } } private KeyValuePair? _selectedKey = null; public KeyValuePair? SelectedKey { get { return _selectedKey; } set { _selectedKey = value; RaisePropertyChanged("SelectedKey"); RaisePropertyChanged("SelectedValue"); } } public TValue SelectedValue { get { return _data[SelectedKey.Value.Key]; } set { _data[SelectedKey.Value.Key] = value; RaisePropertyChanged("SelectedValue"); } } } 

}

Desafortunadamente, todavía no sé cómo pasar objetos de diccionario “generales” … ¿alguna idea?

¡Gracias!

Aclamaciones

Si realmente quieres hacer un ObservableDictionary , te sugiero que crees una clase que implemente tanto IDictionary como INotifyCollectionChanged . Siempre puede usar un Dictionary internamente para implementar los métodos de IDictionary para que no tenga que IDictionary a implementarlo usted mismo.

Como tiene pleno conocimiento de cuándo cambia el Dictionary interno, puede usar ese conocimiento para implementar INotifyCollectionChanged .

  • ObservableDictionary(Of TKey, TValue) – VB.NET
  • ObservableDictionary – C #

Para propósitos históricos y para poner a las personas en la ruta “actual” … Es importante saber que Microsoft ahora resuelve este requisito en su plantilla de la “Página básica” de Windows Store en Visual Studio 2012. Para poder dar soporte a la LayoutAwarePage generan un espacio privado Clase ObservableDictionary.

Sin embargo, implementan una nueva interfaz IObservableMap en lugar de IDictionary directamente. Esta interfaz agrega un evento MapChanged y MapChangedEventHandler, definidos en el espacio de nombres Windows.Foundation.Collections.

El siguiente fragmento es solo la clase ObservableDictionary de LayoutAwarePage.cs generada en la carpeta “Común” de su proyecto:

  ///  /// Implementation of IObservableMap that supports reentrancy for use as a default view /// model. ///  private class ObservableDictionary : IObservableMap { private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs { public ObservableDictionaryChangedEventArgs(CollectionChange change, K key) { CollectionChange = change; Key = key; } public CollectionChange CollectionChange { get; private set; } public K Key { get; private set; } } private Dictionary _dictionary = new Dictionary(); public event MapChangedEventHandler MapChanged; private void InvokeMapChanged(CollectionChange change, K key) { var eventHandler = MapChanged; if (eventHandler != null) { eventHandler(this, new ObservableDictionaryChangedEventArgs(change, key)); } } public void Add(K key, V value) { _dictionary.Add(key, value); InvokeMapChanged(CollectionChange.ItemInserted, key); } public void Add(KeyValuePair item) { Add(item.Key, item.Value); } public bool Remove(K key) { if (_dictionary.Remove(key)) { InvokeMapChanged(CollectionChange.ItemRemoved, key); return true; } return false; } public bool Remove(KeyValuePair item) { V currentValue; if (_dictionary.TryGetValue(item.Key, out currentValue) && Object.Equals(item.Value, currentValue) && _dictionary.Remove(item.Key)) { InvokeMapChanged(CollectionChange.ItemRemoved, item.Key); return true; } return false; } public V this[K key] { get { return _dictionary[key]; } set { _dictionary[key] = value; InvokeMapChanged(CollectionChange.ItemChanged, key); } } public void Clear() { var priorKeys = _dictionary.Keys.ToArray(); _dictionary.Clear(); foreach (var key in priorKeys) { InvokeMapChanged(CollectionChange.ItemRemoved, key); } } public ICollection Keys { get { return _dictionary.Keys; } } public bool ContainsKey(K key) { return _dictionary.ContainsKey(key); } public bool TryGetValue(K key, out V value) { return _dictionary.TryGetValue(key, out value); } public ICollection Values { get { return _dictionary.Values; } } public bool Contains(KeyValuePair item) { return _dictionary.Contains(item); } public int Count { get { return _dictionary.Count; } } public bool IsReadOnly { get { return false; } } public IEnumerator> GetEnumerator() { return _dictionary.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _dictionary.GetEnumerator(); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); int arraySize = array.Length; foreach (var pair in _dictionary) { if (arrayIndex >= arraySize) break; array[arrayIndex++] = pair; } } } 

Un examen más detallado del nuevo espacio de nombres Windows.Foundation.Collections muestra una carga de nuevas interfaces definidas, pero solo se implementó una clase PropertySet . En realidad, esto parece ser un buen observableDiccionario en sí mismo. Pero debe haber una razón por la cual la EM todavía genere un ObservableDictionary privado. Por lo tanto, se requiere un examen más detallado para identificar los pros y los contras.

En resumen, el PropertySet o su propio ObservableDictionary basado en IObservableMap deben resolver los requisitos inmediatos para los proyectos “actuales” de Windows 8 y Phone 8. Sin embargo, para los marcos antiguos (WPF 4 y Phone 7.5) todavía hay más trabajo por hacer.

Sugiero el siguiente artículo, donde se explica cómo implementar un diccionario observable y el código fuente está disponible con una muestra:

http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

Microsoft tiene una implementación de un diccionario observable en el paquete MSFT.ParallelExtensionsExtras disponible a través de Nuget: https://www.nuget.org/packages/ParallelExtensionsExtras/

ObservableConcurrentDictionary

No se puede escribir algo que haga que el diccionario de otra persona, y mucho menos IDictionary, sea observable sin usar alguna forma de reflexión. El problema es que el Diccionario puede ser una subclase con mutadores adicionales (por ejemplo, Ordenar, o Filtro, o lo que sea) que no invocan Agregar y Eliminar y omiten sus eventos como resultado.

Creo que existen marcos de generación de código que te permiten hacer cosas como esta, pero no estoy familiarizado con ellas.