INotifyCollectionChanged
구현을 Stack
및 Queue
으로 찾고 있습니다. 나는 내 자신을 굴릴 수는 있지만 바퀴를 재발 명하고 싶지는 않습니다.관찰 가능한 스택 및 대기열
답변
스택 및 대기열 (거의 정의 됨)을 사용하면 스택 맨 또는 대기열 맨 위에 만 액세스 할 수 있습니다. 그것들은 List
과 구별됩니다. 나는 오프셋 Insert
에서와 Push
를 구현하는 스택의 경우 다음 ObservableCollection
에서 파생에 의해 그것을 할 것입니다, 당신이 당신의 자신을 쓸 수 있지만
가 대답하기 위해 (당신이 하나를 찾을 수없는 이유 때문에, 그건) 0 (그리고 인덱스가 0으로 돌아 오자 팝 후 RemoveAt
인덱스 0); 또는 대기열을 사용하면 목록의 끝에 Add
을 Enqueue
으로 가져올 수 있으며 스택과 마찬가지로 Dequeue
의 첫 번째 항목을 잡고 제거 할 수 있습니다. Insert
, Add
및 RemoveAt
작업은 기본 ObservableCollection
에서 호출되므로 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 제거 이벤트가 항목 위치를 지정해야합니다." 어쨌든이 문제를 해결할 수 있습니까? tnx –
base.Count 누락 된 항목 위치로 나를 위해 그것을 고정. public 새 가상 T Pop() { var item = base.Pop(); this.OnCollectionChanged (새 NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, item, base.Count))); 반품 항목 : } – uli78
나는 받아 들인 대답에이 해결책을 선호한다. 이 기능을 사용하면 스택 (대기열에 비해 처음부터 제거하는 데 비용이 많이 드는)을 사용하여 스택/큐의 성능 예상치와 의미를 유지 관리 할 수 있습니다. – KChaloux
몇 가지 예외를 제외하고, 위의 클래스와 매우 유사한
- 가 게시 소품이 영향을 미칠 수있는 카운트
- 무시 TrimExcess() B/C에 대한 수집 변화를 변경 카운트
- 이벤트를 공개 했으므로 인터페이스에 전송할 필요가 없습니다.
- 적절한 시점에 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(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));
}
}
"ObservableStack"에 대한 첫 번째 접근 방식을 권장합니다. ObservableCollection에서 파생되었거나 더 좋았습니다. 두 번째 접근법은'ObservableQueue'를 위해 더 좋을 것입니다 -'Queue'에서 파생시키고 여러분 자신의 통지를 구현하십시오. 왜냐하면'List'에 내장 된'ObservableQueue'는'Enqueue' 또는'Dequeue'에 대해 O (N) 성능을 가지기 때문에 다른 모든 것은 O (1) 일 것입니다. 대기열에 많은 요소가 있으면 성능에 영향을 미칩니다. –
간단히 INotifyCollectionChanged를 구현하는 일반적인 관찰 가능한 클래스를 만들기로했습니다. 클래스는 내부 스택 및 대기열 메서드를 호출하고 적절한 이벤트를 발생시킵니다. Stack과 Queue 메소드가 상속이 아닌 상속에 비해 컴포지션을 선호하는 이유는 무엇인지 이해하는 데 어려움이 있습니다. – Goran