2010-06-27 3 views

ответ

11

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

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


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

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

Я рекомендую первый подход для «ObservableStack» - получить (или лучше содержать) «ObservableCollection». Второй подход будет лучше для «ObservableQueue» - получить из «Queue» и реализовать ваши собственные уведомления. Это связано с тем, что любой «ObservableQueue», построенный на «List», будет иметь производительность O (N) для «Enqueue» или «Dequeue», тогда как все остальное будет O (1). Это повлияет на производительность, если в очереди будет много элементов. –

+0

Я решил создать общий наблюдаемый класс, который просто реализует INotifyCollectionChanged. Классы вызывают внутренние методы Stack и Queue и поднимают соответствующее событие. Преимущество композиции над наследованием, поскольку методы Stack и Queue не являются виртуальными (у меня возникают проблемы с пониманием причин). – Goran

26

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

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

Привет. После ошибки после Pop() «Событие Remove Collection должно указывать позицию позиции». в любом случае, чтобы исправить это? tnx –

+3

base.Count как отсутствующая позиция позиции зафиксировала это для меня. public new virtual T Pop() { var item = base.Pop(); this.OnCollectionChanged (новый NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, item, base.Count)); возвращенный товар; } – uli78

+0

Я предпочитаю это решение для принятого ответа. Он позволяет вам поддерживать ожидания производительности и семантику стека/очереди, а не просто имитировать его списком (который, например, дорого стоит удалить с самого начала, по сравнению с очередью). – KChaloux

1

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

  1. Publish проп изменены для изменения коллекции для графа
  2. Override TrimExcess() б/с, что может повлиять на граф
  3. Сделанные события публичные, поэтому мне не нужно отбрасывать на интерфейс
  4. Пропускает индекс для сбора, если необходимо,
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)); 
     } 
    }
Смежные вопросы