Наблюдаемый стек и очередь
Я ищу 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; }
}
}
очень похоже на вышеупомянутый класс, за несколькими исключениями:
- опубликовать prop изменен для коллекции изменений для Count
- переопределить TrimExcess () b/c, который может повлиять на Count
- сделал события общедоступными, поэтому мне не нужно бросать в интерфейс
- передает индекс в 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;
}
}