JD2022-TU1/main/tools/framework/JD.Collections/ObservableSet.cs

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&lt;T&gt; 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&lt;T&gt; 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
}
}