Frage

Ich suche nach einer INotifyCollectionChanged Implementierung von Stack und Queue. Ich konnte meine eigene Rolle, aber ich will nicht das Rad neu zu erfinden.

War es hilfreich?

Lösung

Mit Stacks und Queues (fast per Definition) Sie haben nur Zugriff auf die Oberseite des Stapels oder Kopf der Schlange. Es ist, was sie von einem List unterscheidet. (Und ja, das ist, warum haben Sie nicht eine gefunden)

Um Antwort obwohl Sie Ihre eigenen schreiben könnte, würde ich es tun, indem von ObservableCollection abzuleiten, dann im Falle eines Stapels die Push als Insert bei Offset 0 Umsetzung (und Pop als Rückkehr Index 0 dann RemoveAt Index 0); oder mit einer Warteschlange können Sie nur bis zum Ende der Liste zu Add Enqueue, und dem Greifer und entfernen Sie das erste Element, wie mit dem Stapel, für Dequeue. Die Insert, Add und RemoveAt Operationen würden auf dem zugrunde liegenden ObservableCollection und so Ursache des CollectionChanged Ereignis ausgelöst werden, genannt werden.


Sie können auch sagen, dass Sie einfach binden wollen oder benachrichtigt werden, wenn das ein Element, das Sie sollen den Zugriff auf Änderungen haben. Sie würden wieder Ihre eigene Klasse erstellen, die sich von Stapel oder Queue und feuern die Collection Ereignis manuell, wenn:

  • Etwas gedrückt wird auf oder von einem Stapel genommen
  • Etwas aus einer Warteschlange aus der Warteschlange entfernt
  • Etwas in der Warteschlange der Warteschlange, wenn die Warteschlange zuvor leer war

Andere Tipps

Ich laufe in der gleichen Ausgabe und möchte, dass meine Lösung zu anderen teilen. Hoffe, das ist hilfreich für jemanden.

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; }
    }
}

Sehr ähnlich der obigen Klasse, mit einigen Ausnahmen:

  1. prop Publish abhol Änderungen geändert für Count
  2. außer Kraft setzen TrimExcess () b / c, die Count
  3. beeinflussen könnten
  4. Made Ereignisse öffentlich so habe ich nicht zu Guss an die Schnittstelle
  5. Pässe Index Collection bei Bedarf
    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;
}

    }

Ich weiß, es gibt schon ein paar Antworten, aber dachte, ich würde mit meinem etwas zurück geben. Ich habe alles zusammen in den Beiträgen und Kommentaren erwähnt. Es gab nur wenige Dinge, die mich motiviert, dies zu tun:

  • INPC sollte immer Feuer und Flamme für Count wenn Push, Pop oder Clear genannt werden, wie in einem der Pfosten erwähnt.
  • Für Clear, Aktion sollte Reset und Index für die Sammlung Änderungsereignis sein sollte -1 eingestellt werden (die es ohnehin nicht nachkommt, wenn nicht gesetzt, so dass die anderen Beiträge, die haben): . NET docs
  • Für Push / Pop, Aktion sollte Add / Remove und Index für die Sammlung geändert Ereignis sein sollte 0 für einen Stapel sein wird, dass es immer und nur das erste Element, das (man denke stack.GetEnumerator().MoveNext()) maniuplated werden kann.
  • Exposed alle drei Konstrukteure in Stack<T> und Verwendung base() Anrufe, da es keinen Grund gibt, die Logik außer Kraft zu setzen.

Ergebnisse in:

public class ObservableStack<T> : Stack<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
    #region Constructors

    public ObservableStack() : base() { }

    public ObservableStack(IEnumerable<T> collection) : base(collection) { }

    public ObservableStack(int capacity) : base(capacity) { }

    #endregion

    #region Overrides

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

        return item;
    }

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

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

    #endregion

    #region CollectionChanged

    public virtual event NotifyCollectionChangedEventHandler CollectionChanged;

    protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, T item)
    {
        CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(
            action
            , item
            , item == null ? -1 : 0)
        );

        OnPropertyChanged(nameof(Count));
    }

    #endregion

    #region PropertyChanged

    public virtual event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string proertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(proertyName));
    }

    #endregion
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top