Ok so i had trouble even expressing what I needed so i had to build it myself. So what is it?
Well, it’s basically a hashed queue where when you enqueue again an already queued item, you basically put it in the first spot. It’s made as a collection but it still acts as a queue. I needed it for my taskbar which automatically closes the least active item, or the one least used. so here you go:
public class BindableQueueSet<T> : ICollection<T>, INotifyCollectionChanged,INotifyPropertyChanged
{
private readonly ObservableCollection<Pair> que;
private int maxNumber;
private readonly int capacity;
#region Private and protected
private bool AddItemCore(T item)
{
bool result;
var found = que.FirstOrDefault(x => x.Value.Equals(item));
if (found == null)
{
que.Add(new Pair(item, maxNumber++));
result = true;
}
else
{
found.Weight = maxNumber++;
result = false;
}
result = CleanUp() || result;
return result;
}
private Pair Find(T item)
{
return que.FirstOrDefault(x => x.Value.Equals(item));
}
private bool CleanUp()
{
if (capacity >= que.Count) return false;
Pair lightestPair = que[0];
foreach (var pair in que)
{
if (pair.Weight < lightestPair.Weight)
lightestPair = pair;
}
que.Remove(lightestPair);
return true;
}
#endregion
public BindableQueueSet(int capacity)
{
if (capacity < 1) throw new ArgumentException();
this.capacity = capacity;
que = new ObservableCollection<Pair>();
que.CollectionChanged += (s, e) => OnCollectionChanged(e);
((INotifyPropertyChanged) que).PropertyChanged += (s, e) => OnPropertyChanged(e);
}
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventArgs enew;
switch (e.Action)
{
case NotifyCollectionChangedAction.Replace:
enew = new NotifyCollectionChangedEventArgs(e.Action,
e.NewItems != null && e.NewItems.Count > 0
? ((Pair) e.NewItems[0]).Value:default(T),
e.OldItems != null && e.OldItems.Count > 0
? ((Pair) e.OldItems[0]).Value:default(T),
e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Add:
enew = new NotifyCollectionChangedEventArgs(e.Action,
e.NewItems != null && e.NewItems.Count > 0
? ((Pair)e.NewItems[0]).Value : default(T),
e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
enew = new NotifyCollectionChangedEventArgs(e.Action,
e.OldItems != null && e.OldItems.Count > 0
? ((Pair)e.OldItems[0]).Value : default(T),
e.OldStartingIndex);
break;
default:
enew = new NotifyCollectionChangedEventArgs(e.Action);
break;
}
if (CollectionChanged != null)
CollectionChanged(this, enew);
}
public IEnumerator<T> GetEnumerator()
{
return new QueueEnum(que.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
AddItemCore(item);
}
public void Clear()
{
que.Clear();
}
public bool Contains(T item)
{
return Find(item) != null;
}
public void CopyTo(T[] array, int arrayIndex)
{
while (arrayIndex < array.Length)
{
AddItemCore(array[arrayIndex]);
arrayIndex++;
}
}
public bool Remove(T item)
{
var found = Find(item);
return que.Remove(found);
}
public int Count
{
get { return que.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
private class Pair
{
public int Weight { get; set; }
public T Value { get; private set; }
public Pair(T value, int weight)
{
Value = value;
Weight = weight;
}
}
private class QueueEnum : IEnumerator<T>
{
private readonly IEnumerator<Pair> queEnum;
public QueueEnum(IEnumerator<Pair> queEnum)
{
this.queEnum = queEnum;
}
public void Dispose()
{
queEnum.Dispose();
}
public bool MoveNext()
{
return queEnum.MoveNext();
}
public void Reset()
{
queEnum.Reset();
}
public T Current
{
get { return queEnum.Current.Value; }
}
object IEnumerator.Current
{
get { return Current; }
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Leave a Comment