34 votes

Quelle collection .Net pour ajouter plusieurs objets à la fois et être averti?

Envisageait System.Collections.ObjectModel ObservableCollection<T> classe. C'est étrange parce que

  • il a une Méthode Add qui prend un élément seulement. Pas de AddRange ou l'équivalent.
  • l'événement de Notification des arguments a un NewItems de la propriété, qui est une IList (d'objets.. pas de T)

Mon besoin est d'ajouter un lot d'objets à une collection et l'auditeur obtient également le lot dans le cadre de la notification. Ai-je raté quelque chose avec ObservableCollection ? Est-il une autre classe qui répond à mon spec?

Mise à jour: Ne voulez pas rouler mes propres autant que possible. Je dois construire dans ajouter/supprimer/modifier etc.. tout un tas de trucs.


Liées Q:
http://stackoverflow.com/questions/670577/observablecollection-doesnt-support-addrange-method-so-i-get-notified-for-each

19voto

fryguybob Points 2886

Il semble que l'interface INotifyCollectionChanged permette la mise à jour lorsque plusieurs éléments ont été ajoutés, donc je ne sais pas pourquoi ObservableCollection<T> n'a pas de AddRange . Vous pouvez créer une méthode d'extension pour AddRange , mais cela provoquerait un événement pour chaque élément ajouté. Si cela n'est pas acceptable, vous devriez pouvoir hériter de ObservableCollection<T> comme suit:

 public class MyObservableCollection<T> : ObservableCollection<T>
{
    // matching constructors ...

    bool isInAddRange = false;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        // intercept this when it gets called inside the AddRange method.
        if (!isInAddRange) 
            base.OnCollectionChanged(e);
    }


    public void AddRange(IEnumerable<T> items)
    {
         isInAddRange = true;
         foreach (T item in items)
            Add(item);
         isInAddRange = false;

         var e = new NotifyCollectionChangedEventArgs(
             NotifyCollectionChangedAction.Add,
             items.ToList());
         base.OnCollectionChanged(e);
    }
}
 

6voto

Gishu Points 59012

Eh bien, l'idée est la même que celle de fryguybob - un peu bizarre que ObservableCollection soit à moitié fait. L'événement args pour cette chose n'utilise même pas Generics .. me faisant utiliser un IList (c'est le cas .. hier :) Tested Snippet suit ...

 using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace MyNamespace
{
    public class ObservableCollectionWithBatchUpdates<T> : ObservableCollection<T>
    {
        public void AddRange(ICollection<T> obNewItems)
        {
            IList<T> obAddedItems = new List<T>();
            foreach (T obItem in obNewItems)
            {
                Items.Add(obItem);
                obAddedItems.Add(obItem);
            }
            NotifyCollectionChangedEventArgs obEvtArgs = new NotifyCollectionChangedEventArgs(
               NotifyCollectionChangedAction.Add, 
               obAddedItems as System.Collections.IList);
            base.OnCollectionChanged(obEvtArgs);
        }

    }
}
 

4voto

Kyralessa Points 76456

Non seulement System.Collections.ObjectModel.Collection<T> un bon pari, mais dans les documents d'aide, il y a un exemple de la façon de remplacer ses différentes méthodes protégées afin d'obtenir une notification. (Faites défiler jusqu'à l'exemple 2.)

4voto

Sam Saffron Points 56236

Si vous utilisez l'un des au-dessus des implémentations d'envoyer un complément de la gamme de commandement et de lier le observablecolletion à une liste, vous obtiendrez cette erreur méchante.

NotSupportedException
 au Système.De Windows.Les données.ListCollectionView.ValidateCollectionChangedEventArgs(NotifyCollectionChangedEventArgs e)
 au Système.De Windows.Les données.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
 au Système.Les Collections.Spécialisés.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
 au Système.Les Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)

La mise en œuvre, je suis allé avec utilise l'événement de Réinitialisation qui est le plus uniformément mis en place autour du framework WPF:

    public void AddRange(IEnumerable<T> collection)
    {
        foreach (var i in collection) Items.Add(i);
        OnPropertyChanged("Count");
        OnPropertyChanged("Item[]");
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

2voto

David Mohundro Points 5158

Si vous souhaitez hériter d'une collection quelconque, vous feriez probablement mieux d'hériter de System.Collections.ObjectModel.Collection car il fournit des méthodes virtuelles de remplacement. Vous devrez masquer les méthodes hors de List si vous suivez cette voie.

Je ne suis au courant d'aucune collection intégrée qui offre cette fonctionnalité, mais j'aimerais bien être corrigée :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X