227 lines
6.6 KiB
C#
227 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using JD.Collections.Interfaces;
|
|
|
|
namespace JD.Collections
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
[Serializable]
|
|
public class ObservableSet<T> : Set<T>, IObservableCollection<T>
|
|
{
|
|
#region Variables
|
|
|
|
[NonSerialized]
|
|
private int m_updateLevel;
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Creates a new ObservableSet. The Equals method and GetHashCode method on T
|
|
/// will be used to compare items for equality.
|
|
/// </summary>
|
|
///<remarks>
|
|
/// Items that are null are permitted, and will be sorted before all other items.
|
|
///</remarks>
|
|
public ObservableSet()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new ObservableSet. The Equals and GetHashCode method of the passed comparer object
|
|
/// will be used to compare items in this set.
|
|
/// </summary>
|
|
/// <param name="equalityComparer">An instance of IEqualityComparer<T> that will be used to compare items.</param>
|
|
public ObservableSet(IEqualityComparer<T> equalityComparer)
|
|
: base(equalityComparer)
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new ObservableSet. The Equals method and GetHashCode method on T
|
|
/// will be used to compare items for equality.
|
|
/// </summary>
|
|
///<remarks>
|
|
/// Items that are null are permitted.
|
|
///</remarks>
|
|
/// <param name="collection">A collection with items to be placed into the Set.</param>
|
|
public ObservableSet(IEnumerable<T> collection)
|
|
: base(collection)
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new ObservableSet. The Equals and GetHashCode method of the passed comparer object
|
|
/// will be used to compare items in this set. The set is
|
|
/// initialized with all the items in the given collection.
|
|
/// </summary>
|
|
/// <param name="collection">A collection with items to be placed into the Set.</param>
|
|
/// <param name="equalityComparer">An instance of IEqualityComparer<T> that will be used to compare items.</param>
|
|
public ObservableSet(IEnumerable<T> collection, IEqualityComparer<T> equalityComparer)
|
|
: base(collection, equalityComparer)
|
|
{
|
|
|
|
}
|
|
|
|
#endregion Constructors
|
|
|
|
#region IObservableCollection<TValue> Members
|
|
|
|
/// <summary>
|
|
/// Whether this set is updating.
|
|
/// </summary>
|
|
public bool IsUpdating
|
|
{
|
|
get
|
|
{
|
|
return m_updateLevel > 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Suspends all events for this set.
|
|
/// </summary>
|
|
public void BeginUpdate()
|
|
{
|
|
++m_updateLevel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resumes events for this set.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool EndUpdate()
|
|
{
|
|
if (--m_updateLevel == 0)
|
|
{
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.EndUpdated, default(T)));
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Register an item in the list (for example, can bind to its events)
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
protected virtual void RegisterItem(T item)
|
|
{
|
|
if (item is IObservableItem)
|
|
{
|
|
((IObservableItem)item).Changed += internal_itemChanged;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unregister an item from the list (for example, unbind from its events).
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
protected virtual void UnregisterItem(T item)
|
|
{
|
|
if (item is IObservableItem)
|
|
{
|
|
((IObservableItem)item).Changed -= internal_itemChanged;
|
|
}
|
|
}
|
|
|
|
#region Handlers
|
|
|
|
private void internal_itemChanged(object sender, EventArgs e)
|
|
{
|
|
if (sender is T)
|
|
{
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.ItemChanged, (T)sender));
|
|
}
|
|
else
|
|
{
|
|
System.Diagnostics.Debug.Assert(false, "Bad implementation of the IObservableItem interface. The object should be the sender of the event args");
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.ItemChanged, default(T)));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// Triggered when the collection changes.
|
|
/// </summary>
|
|
public event EventHandler<CollectionChangedEventArgs<T>> CollectionChanged;
|
|
|
|
/// <summary>
|
|
/// Triggers the <see cref="CollectionChanged"/> event.
|
|
/// </summary>
|
|
/// <param name="e">Event Args.</param>
|
|
protected virtual void OnCollectionChanged(CollectionChangedEventArgs<T> e)
|
|
{
|
|
CollectionChanged?.Invoke(this, e);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Set Members
|
|
|
|
/// <summary>
|
|
/// Overriden.
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <returns></returns>
|
|
public override bool Add(T item)
|
|
{
|
|
if (!base.Add(item))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RegisterItem(item);
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.ItemAdded, item));
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overriden.
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <returns></returns>
|
|
public override bool Remove(T item)
|
|
{
|
|
if (base.Remove(item))
|
|
{
|
|
UnregisterItem(item);
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.ItemRemoved, item));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overriden.
|
|
/// </summary>
|
|
public override void Clear()
|
|
{
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.Clearing, default(T)));
|
|
|
|
foreach (T item in this)
|
|
{
|
|
UnregisterItem(item);
|
|
}
|
|
|
|
base.Clear();
|
|
OnCollectionChanged(new CollectionChangedEventArgs<T>(CollectionChangeAction.Cleared, default(T)));
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|