web-dev-qa-db-fra.com

Supprimer un élément d'une ObservableCollection dans un gestionnaire d'événements CollectionChanged

J'espère pouvoir rejeter certains éléments après leur ajout à une ObservableCollection. Je ne parviens pas à sous-classer ObservableCollection ni à utiliser un type de vue. Il semble donc que je sois limité à l'utilisation du gestionnaire d'événement défini (CollectionChanged) pour effectuer un .Remove () sur les éléments interdits. Cela ne pose pas de problème si les éléments existent pendant la courte période qui sépare l'événement, puis son traitement. les articles ne doivent tout simplement pas persister dans la collection. L'appel de .Remove () dans le gestionnaire d'événements CollectionChanged ne semble pas être autorisé. Au moment de l'exécution, .NET lève une exception InvalidOperationException:

"Impossible de changer ObservableCollection lors d'un événement CollectionChanged."

Personnellement, je pense que .NET devrait me permettre de le faire. Si je crée une boucle infinie, c'est ma faute.

Le code que je voudrais utiliser ressemblerait à ceci:

myCollection.CollectionChanged += (sender, args) =>
{
    if (args.Action == NotifyCollectionChangedAction.Remove)
        return;
    foreach (var itm in myCollection)
    {
        if (itm.name == "Fred")
            myCollection.Remove(itm);
    }
}

Je ne suis pas sûr de mes options. L'utilisation d'un répartiteur ne semble pas fonctionner. Déclencher un autre événement et placer l'appel .Remove dans un autre gestionnaire est la seule autre option qui me vienne à l'esprit.

11
ebpa

Check out Erreurs courantes avec Observable Collection .

Ceci dit, si vous voulez toujours aller dans cette voie - vous pouvez faire tourner un nouveau sujet

17
Anurag Ranjhan

si vous voulez vraiment modifier une collection, vous allez vouloir parcourir une copie de la collection. c'est parce que vous essayez de modifier la collection dans la boucle foreach qui vous cause du chagrin.

exemple

var copy = new ObservableCollection<YourType>(collection)
foreach(var item in copy)
{
    if(item.Name == "Fred")
    {
        collection.Remove(item);
    }

}

cela dit, je suis d’accord avec Anurag pour dire que vous ne devriez pas faire ce genre de chose avec une collection observable et certainement pas dans un événement CollectionChanged.

12
tam

Utilisé dans le oncollectionchanged et ça marche (exemple WPF et MVVM):

new System.Threading.Thread(t =>
{
  Application.Current.Dispatcher.Invoke((Action)delegate
  {
    OnHoldMessages.Add(_selectedOnHoldMessage);
    RaisePropertyChanged(propertyName: "OnHoldMessages");
  });
}).Start();
0
Mark

utilisez ToList() pour parcourir la liste.

foreach(var item in collection.ToList())
{
    if(item.Name == "Fred")
    {
        collection.Remove(item);
    }
}
0
Gilad