Saltar al contenido

Cómo crear una colección observable personalizada usando ConcurrentDictionary, INotifyCollectionChanged, INotifyPropertyChanged

Esta es la solución más válida que encomtrarás aportar, sin embargo obsérvala detenidamente y valora si se puede adaptar a tu proyecto.

Solución:

No pude hacer funcionar la muestra de OP. Levantó una carga troncal de excepciones de subprocesos cruzados todo el tiempo sin importar lo que intentara.

Sin embargo, dado que también necesitaba una colección segura para subprocesos que implemente las interfaces INotifyCollectionChanged e INotifyPropertyChanged, busqué en Google y encontré una implementación de los propios chicos de Microsoft.

Descargue este archivo http://code.msdn.microsoft.com/Samples-for-Parallel-b4b76364 y ​​busque ObservableConcurrentDictionary.cs en el archivo.

¡Funciona de maravilla!

Revisando rápidamente su código sin ninguna explicación de su parte, solo puedo adivinar. No creo que establecer Acción en NotifyCollectionChangedEventArgs sea suficiente. también hay NewItems, OldItems properties, que le dicen al suscriptor qué elementos cambiaron.

Tenga en cuenta también que, si bien se trata de colecciones, muchos componentes de WPF solo admiten el cambio de un solo elemento a la vez a través de DataBinding.

Desarrollé una versión ajustada de un ObservableConcurrentDictionnary, comente/sugiera…

… donde TValue : Object usa tu clase en lugar de Object…

qurlet

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;

namespace Collections

    public class ObservableConcurrentDictionary : ConcurrentDictionary, INotifyCollectionChanged, INotifyPropertyChanged
        where TValue : Object , new()
    
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs changeAction)
        
            var eh = CollectionChanged;
            if (eh == null) return;

            eh(this, changeAction);

            OnPropertyChanged();
        

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged()
        
            var eh = PropertyChanged;
            if (eh == null) return;

            // All properties : Keys, Values, Count, IsEmpty
            eh(this, new PropertyChangedEventArgs(null));
        

        #region Ctors
        public ObservableConcurrentDictionary()
            : base()
        

        

        public ObservableConcurrentDictionary(IEnumerable> collection)
            : base(collection)
        

        

        public ObservableConcurrentDictionary(IEqualityComparer comparer)
            : base(comparer)
        

        

        public ObservableConcurrentDictionary(int concurrencyLevel, int capacity)
            : base(concurrencyLevel, capacity)
        

        

        public ObservableConcurrentDictionary(IEnumerable> collection, IEqualityComparer comparer)
            : base(collection, comparer)
        

        

        public ObservableConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer comparer)
            : base(concurrencyLevel, capacity, comparer)
        

        

        public ObservableConcurrentDictionary(int concurrencyLevel, IEnumerable> collection, IEqualityComparer comparer)
            : base(concurrencyLevel, collection, comparer)
        

        
        #endregion

        public new void Clear()
        
            // Clear dictionary
            base.Clear();
            // Raise event
            OnCollectionChanged(changeAction: new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        

        public new TValue AddOrUpdate(Int32 key, Func addValueFactory,
            Func updateValueFactory)
        
            bool isUpdated = false;
            TValue oldValue = default(TValue);

            TValue value = base.AddOrUpdate(key, addValueFactory, (k, v) =>
            
                isUpdated = true;
                oldValue = v;
                return updateValueFactory(k, v);
            );

            if (isUpdated) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, oldValue));

            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value));
            return value;
        

        public new TValue AddOrUpdate(Int32 key, TValue addValue, Func updateValueFactory)
        
            bool isUpdated = false;
            TValue oldValue = default(TValue);

            TValue value = base.AddOrUpdate(key, addValue, (k, v) =>
            
                isUpdated = true;
                oldValue = v;
                return updateValueFactory(k, v);
            );

            if (isUpdated) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, oldValue));

            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value));
            return value;
        

        public new TValue GetOrAdd(Int32 key, Func addValueFactory)
        
            bool isAdded = false;

            TValue value = base.GetOrAdd(key, k =>
            
                isAdded = true;
                return addValueFactory(k);
            );

            if (isAdded) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value));

            return value;
        

        public new TValue GetOrAdd(Int32 key, TValue value)
        
            return GetOrAdd(key, k => value);
        

        public new bool TryAdd(Int32 key, TValue value)
        
            bool tryAdd = base.TryAdd(key, value);

            if (tryAdd) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value));

            return tryAdd;
        

        public new bool TryRemove(Int32 key, out TValue value)
        
            // Stores tryRemove
            bool tryRemove = base.TryRemove(key, out value);

            // If removed raise event
            if (tryRemove) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, value));

            return tryRemove;
        

        public new bool TryUpdate(Int32 key, TValue newValue, TValue comparisonValue)
        
            // Stores tryUpdate
            bool tryUpdate = base.TryUpdate(key, newValue, comparisonValue);

            if (tryUpdate) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newValue, comparisonValue));

            return tryUpdate;
        

    

Si posees alguna cuestión o capacidad de beneficiar nuestro división puedes realizar una aclaración y con deseo lo leeremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *