可观察的堆栈和队列

我正在寻找StackQueueINotifyCollectionChanged实现。 我可以自己动手,但我不想重新发明轮子。

使用堆栈和队列(几乎按定义),您只能访问堆栈顶部或队列头部。 这是它们与List区别。 (所以,这就是你没找到的原因)

虽然您可以自己编写,但我会通过从ObservableCollection派生来实现,然后在堆栈的情况下实现Push作为Insert偏移0(并弹出作为返回索引0然后RemoveAt索引0); 或者使用队列,你可以只Add到列表的末尾以进行入队,并抓取并删除第一个项目,就像堆栈一样,用于Dequeue 。 将在底层的ObservableCollection上调用InsertAddRemoveAt操作,因此会触发CollectionChanged事件。


您可能也会说,您只是想在您应该有权访问的项目发生更改时绑定或得到通知。 您将再次创建自己的类,派生自Stack或Queue,并在以下情况下手动触发CollectionChanged事件:

  • 某些东西被推入或从堆栈中弹出
  • 有些东西从队列中出队
  • 当队列先前为空时,队列中排队的东西

我遇到了同样的问题,并希望与其他人分享我的解决方案。 希望这对某人有帮助。

 public class ObservableStack : Stack, INotifyCollectionChanged, INotifyPropertyChanged { public ObservableStack() { } public ObservableStack(IEnumerable collection) { foreach (var item in collection) base.Push(item); } public ObservableStack(List 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. 发布道具已更改为Count的集合更改
  2. 覆盖可能影响Count的TrimExcess()b / c
  3. 使事件公开,所以我不必强制转换到界面
  4. 适当时将索引传递给collectionschanged
  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; } }