我在找INotifyCollectionChanged
執行Stack
和Queue
。我可以推出自己的遊戲,但我不想重新發明輪子。可觀察堆棧和隊列
可觀察堆棧和隊列
回答
使用堆棧和隊列(幾乎按定義),您只能訪問堆棧頂部或隊列頭部。這是區別於List
。 (所以,這就是爲什麼你還沒有找到一個)
要回答雖然你可以寫你自己的,我會從ObservableCollection
得出這樣做,那麼在執行Push
爲Insert
在堆棧偏移的情況下, 0(並且彈出作爲返回索引0,然後RemoveAt
索引0);或者可以使用隊列Add
到列表末尾Enqueue
,然後抓取並刪除第一項,如堆棧中的Dequeue
。將在底層ObservableCollection
上調用Insert
,Add
和RemoveAt
操作,從而導致CollectionChanged
事件被觸發。
你可能也會說,你只是想綁定或通知,當你應該有一個項目可以訪問更改。你會再次創建自己的類,從堆棧或隊列導出,並手動觸發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; }
}
}
嗨。在Pop()之後出現錯誤「Collection Remove事件必須指定項目位置」。有任何解決這個問題的方法嗎? tnx – 2012-11-24 06:02:52
base.Count作爲缺失項目的位置固定它給我。() public new virtual T Pop() var item = base.Pop(); this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,item,base.Count)); 退貨項目; } – uli78 2013-01-15 06:33:21
我更喜歡這個解決方案的接受答案。它可以讓你保持堆棧/隊列的性能預期和語義,而不僅僅是用一個列表來模擬它(例如,與一個隊列相比,從一開始就很昂貴)。 – KChaloux 2014-04-24 18:29:23
非常類似上面的類,有一些例外:
- 發佈道具變更爲計數
- 覆蓋TrimExcess()B/C,可能會影響集合改變計數
- 公開發布活動,因此我無需投放到界面
- 合適時通過索引更改
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(ClrExtensions.PropertyName(() => 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(ClrExtensions.PropertyName(() => Count));
}
}
- 1. 角4 MEAN堆棧可觀察
- 2. 堆棧和隊列用java
- 3. 在堆棧和隊列
- 4. 隊列+堆棧C++
- 5. 使用隊列堆棧
- 6. Android的隊列VS堆棧
- 7. cuda中的遞歸/堆棧和隊列
- 8. 堆棧和隊列,爲什麼?
- 9. 比較隊列和堆棧的內容
- 10. java - 堆棧和隊列混淆
- 11. 堆棧和隊列的使用情況?
- 12. Java觀察者和可觀察的
- 13. 在C++中鏈接雙棧鏈表和堆棧和隊列類
- 14. RxJS:可觀察對象和單觀察者的遞歸列表
- 15. 是否可以使用ArrayLists以Java編寫隊列和堆棧?
- 16. 基於陣列和基於列表的堆棧和隊列
- 17. 在應用程序中觀察堆棧和堆上的對象的值類型
- 18. 列表,數組,堆棧隊列?
- 19. RxJs堆棧觀測
- 20. 堆棧vs排隊?
- 21. 敲除的ForEach和可觀察陣列
- 22. 敲除和可觀察陣列失配
- 23. 使可觀察陣列的所有項目可觀察
- 24. 觀察員可以觀察多個可觀察物嗎?
- 25. 我想實現一個隊列,將反轉堆棧和打印堆棧FIFO?
- 26. 可觀察列表Nhibernate
- 27. 可觀察到的序列
- 28. 角 - rxjs可觀察陣列
- 29. 如何實現兩個堆棧隊列
- 30. 使用兩個堆棧的隊列
我推薦「ObservableStack」的第一種方法 - 派生自(或更好的,包含)一個ObservableCollection。第二種方法對'ObservableQueue'會更好 - 從'Queue'派生並實現您自己的通知。這是因爲構建在List上的任何ObservableQueue對於Enqueue或Dequeue都具有O(N)性能,而其他所有內容都是O(1)。如果隊列中有很多元素,這會對性能產生影響。 – 2010-06-27 13:53:06
我決定做一個簡單實現INotifyCollectionChanged的通用可觀測類。類調用內部堆棧和隊列方法,並引發相應的事件。由於堆棧和隊列方法不是虛擬的(我無法理解爲什麼),所以對繼承有利。 – Goran 2010-06-27 15:53:23