Pile Observable et File d'attente

je cherche un INotifyCollectionChanged implémentation de Stack et Queue . Je pouvais rouler mon propre mais je ne veux pas réinventer la roue.

14
demandé sur skypjack 2010-06-27 14:56:53

3 réponses

avec des piles et des files d'attente (presque par définition), vous n'avez accès qu'au sommet de la pile ou à la tête de la file d'attente. C'est ce qui les différencie d'un List . (et donc, c'est pourquoi vous n'avez pas trouvé)

pour répondre bien que vous puissiez écrire le vôtre, je le ferais en dérivant de ObservableCollection , puis dans le cas d'une pile mettant en œuvre le Push comme un Insert à l'offset 0 (et pop comme indice de retour 0 puis RemoveAt index 0); ou avec une file d'attente vous pourriez juste Add à la fin de la liste à Enqueue , et le grab et enlever le premier élément, comme avec la pile, pour Dequeue . Les opérations Insert , Add et RemoveAt seraient appelées sur le ObservableCollection sous-jacent et provoqueraient ainsi le déclenchement de l'événement CollectionChanged .


vous pourriez également dire que vous voulez simplement lier ou être notifié lorsque le seul élément que vous êtes censé avoir accès changer. Vous créeriez à nouveau votre propre classe, dérivée de la pile ou de la file, et déclencheriez l'événement modifié par collection manuellement quand:

  • quelque Chose est repoussé ou de maïs à partir d'une pile
  • quelque Chose est retiré de la file d'attente
  • quelque chose est mis en file d'attente, alors que la file d'attente était vide
9
répondu Kieren Johnstone 2010-06-27 11:21:33

j'ai rencontré le même problème et je veux partager ma solution avec d'autres. Espérons que cela est utile à quelqu'un.

public class ObservableStack<T> : Stack<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
    public ObservableStack()
    {
    }

    public ObservableStack(IEnumerable<T> collection)
    {
        foreach (var item in collection)
            base.Push(item);
    }

    public ObservableStack(List<T> list)
    {
        foreach (var item in list)
            base.Push(item);
    }


    public new virtual void Clear()
    {
        base.Clear();
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    public new virtual T Pop()
    {
        var item = base.Pop();
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
        return item;
    }

    public new virtual void Push(T item)
    {
        base.Push(item);
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
    }


    public virtual event NotifyCollectionChangedEventHandler CollectionChanged;


    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        this.RaiseCollectionChanged(e);
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        this.RaisePropertyChanged(e);
    }


    protected virtual event PropertyChangedEventHandler PropertyChanged;


    private void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (this.CollectionChanged != null)
            this.CollectionChanged(this, e);
    }

    private void RaisePropertyChanged(PropertyChangedEventArgs e)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, e);
    }


    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add { this.PropertyChanged += value; }
        remove { this.PropertyChanged -= value; }
    }
}
26
répondu 0xbadf00d 2011-06-05 19:15:41

Très similaire à la classe ci-dessus, à quelques exceptions près:

  1. publier la prop modifiée pour les changements de collection pour le compte
  2. Remplacer TrimExcess() b/c qui pourrait affecter le Comte
  3. des manifestations publiques, donc je ne pas avoir à jeter de l'interface
  4. Passe de l'indice de collectionchanged lorsque cela est approprié
    public class ObservableStack : Stack, INotifyPropertyChanged, INotifyCollectionChanged
    {
      public ObservableStack(IEnumerable collection) : base(collection) {}
      public ObservableStack() { } 

      public event PropertyChangedEventHandler PropertyChanged = delegate { };
      public event NotifyCollectionChangedEventHandler CollectionChanged = delegate { };

      protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, List items, int? index = null)
      {
        if (index.HasValue)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, items, index.Value));
        }
        else
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, items));
        }
         OnPropertyChanged(GetPropertyName(() => Count));
      }

      protected virtual void OnPropertyChanged(string propName)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }

      public new virtual void Clear()
      {
        base.Clear();
        OnCollectionChanged(NotifyCollectionChangedAction.Reset, null);
      }

      public new virtual T Pop()
      {
        var result = base.Pop();
        OnCollectionChanged(NotifyCollectionChangedAction.Remove, new List() { result }, base.Count);
        return result;
      }

      public new virtual void Push(T item)
      {
        base.Push(item);
        OnCollectionChanged(NotifyCollectionChangedAction.Add, new List() { item }, base.Count - 1);
      }   

      public new virtual void TrimExcess()
      {
        base.TrimExcess();
        OnPropertyChanged(GetPropertyName(() => Count));
      }

String GetPropertyName(Expression> propertyId)
{
   return ((MemberExpression)propertyId.Body).Member.Name;
}

    }
0
répondu outbred 2018-03-17 23:50:14