Наблюдаемый стек и очередь

Я ищу INotifyCollectionChanged реализация Stack и Queue. Я мог бы свернуть свой собственный, но я не хочу изобретать колесо.

3 ответов


со стеками и очередями (почти по определению) у вас есть доступ только к верхней части стека или голове очереди. Это то, что отличает их от List. (и поэтому вы его не нашли)

чтобы ответить, хотя вы могли бы написать свой собственный, я бы сделал это, исходя из ObservableCollection, то в случае стека реализации Push как Insert при смещении 0 (и pop как возвращающий индекс 0 тогда RemoveAt индекс 0); или в очереди, вы могли бы просто Add для конец списка Enqueue, и захватить и удалить первый элемент, как со стеком, для Dequeue. The Insert, Add и RemoveAt операции будут вызываться на базовом ObservableCollection и так вызывают CollectionChanged событие, чтобы быть уволен.


вы также можете сказать, что вы просто хотите привязать или получить уведомление, когда один элемент, который вы должны иметь доступ к изменениям. Вы снова создадите свой собственный класс, производный от Stack или Queue, и запустите CollectionChanged событие вручную, когда:

  • что-то нажимается или выскакивает из стека
  • что-то выведено из очереди
  • что-то стоит в очереди, когда очередь была ранее пустой

я сталкиваюсь с той же проблемой и хочу поделиться своим решением с другими. Надеюсь, это кому-то поможет.

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

очень похоже на вышеупомянутый класс, за несколькими исключениями:

  1. опубликовать prop изменен для коллекции изменений для Count
  2. переопределить TrimExcess () b/c, который может повлиять на Count
  3. сделал события общедоступными, поэтому мне не нужно бросать в интерфейс
  4. передает индекс в collectionchanged при необходимости
    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;
}

    }