Pile Observable et File d'attente
je cherche un INotifyCollectionChanged
implémentation de Stack
et Queue
. Je pouvais rouler mon propre mais je ne veux pas réinventer la roue.
3 réponses
avec des piles et des files d'attente (presque par définition), vous n'avez accès qu'au sommet de la pile ou à la tête de la file d'attente. C'est ce qui les différencie d'un List
. (et donc, c'est pourquoi vous n'avez pas trouvé)
pour répondre bien que vous puissiez écrire le vôtre, je le ferais en dérivant de ObservableCollection
, puis dans le cas d'une pile mettant en œuvre le Push
comme un Insert
à l'offset 0 (et pop comme indice de retour 0 puis RemoveAt
index 0); ou avec une file d'attente vous pourriez juste Add
à la fin de la liste à Enqueue
, et le grab et enlever le premier élément, comme avec la pile, pour Dequeue
. Les opérations Insert
, Add
et RemoveAt
seraient appelées sur le ObservableCollection
sous-jacent et provoqueraient ainsi le déclenchement de l'événement CollectionChanged
.
vous pourriez également dire que vous voulez simplement lier ou être notifié lorsque le seul élément que vous êtes censé avoir accès changer. Vous créeriez à nouveau votre propre classe, dérivée de la pile ou de la file, et déclencheriez l'événement modifié par collection manuellement quand:
- quelque Chose est repoussé ou de maïs à partir d'une pile
- quelque Chose est retiré de la file d'attente
- quelque chose est mis en file d'attente, alors que la file d'attente était vide
j'ai rencontré le même problème et je veux partager ma solution avec d'autres. Espérons que cela est utile à quelqu'un.
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; }
}
}
Très similaire à la classe ci-dessus, à quelques exceptions près:
- publier la prop modifiée pour les changements de collection pour le compte
- Remplacer TrimExcess() b/c qui pourrait affecter le Comte
- des manifestations publiques, donc je ne pas avoir à jeter de l'interface
- Passe de l'indice de collectionchanged lorsque cela est approprié
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;
}
}