Skip to content

Instantly share code, notes, and snippets.

@WildGenie
Created March 6, 2017 21:16
Show Gist options
  • Save WildGenie/607d15ae665dc199da0f5510d06e8997 to your computer and use it in GitHub Desktop.
Save WildGenie/607d15ae665dc199da0f5510d06e8997 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Text;
namespace PamServices.Classes {
//*---* *------------------------------------------------------*
///<summary>
/// Class KeyedObservableCollection describes a collection
/// that holds and maintains keyes taken from the collection
/// objects.
///</summary>
///<remarks>
/// This class together an EqualityComparer class KeysEqual
/// assist you to normalize keys of class string for comparison.
///</remarks>
///
public class KeyedObservableCollection<TKey, TItem> : KeyedCollection<TKey, TItem>, INotifyCollectionChanged {
private Func<TItem, TKey> _getKeyFromItem; //*---> e.g. (Func<MyData, string>)((d) => d.MyKey);
private Func<TKey, TKey> _normalizeKey; //*---> e.g. (Func<string, string>)((s) => s.ToLowerInvariant());
private KeysEqual<TKey> comparer;
//*---> Properties and Indexer
public Dictionary<TKey, TItem> ScenarioNames { get { return base.Dictionary as Dictionary<TKey, TItem>; } }
public new TItem this[TKey key] { get { return base[_normalizeKey(key)]; } }
//*---> Constructors
/// <summary>Creates an object using unnormalized strings as keys.</summary>
/// <param name="getKeyFromItem">specifies a delegate to get the key from item.</param>
public KeyedObservableCollection(Func<TItem, TKey> getKeyFromItem) : base() {
if (getKeyFromItem == null)
throw new ArgumentNullException(string.Format("\"getKeyFromItem\" - Delegate to get the key as a {0} from {1} must be specified.", typeof(TKey).Name, typeof(TItem).Name));
this.comparer = new KeysEqual<TKey>();
this._normalizeKey = this.comparer.NormalizeKey;
this._getKeyFromItem = getKeyFromItem;
}
/// <summary>Creates an object using normalized keys.</summary>
/// <param name="getKeyFromItem">specifies a delegate to get the key from item.</param>
/// <param name="comparer">specifies a comparer of class KeysEqual initialized with a delegate to normalize keys.</param>
public KeyedObservableCollection(Func<TItem, TKey> getKeyFromItem, KeysEqual<TKey> comparer)
: base(comparer) {
if (getKeyFromItem == null)
throw new ArgumentNullException(string.Format("\"getKeyFromItem\" - Delegate to get the key as a {0} from {1} must be specified.", typeof(TKey).Name, typeof(TItem).Name));
this.comparer = base.Comparer as KeysEqual<TKey>;
this._normalizeKey = this.comparer.NormalizeKey;
this._getKeyFromItem = getKeyFromItem;
}
//*---> New methods or wrappers for normalizing the keys
public void Replace(TItem item, TItem newItem) {
this.SetItem(base.IndexOf(item), newItem);
}
public new bool Remove(TKey key) {
return base.Remove(_normalizeKey(key));
}
public new bool Remove(TItem item) {
return base.Remove(item);
}
public new bool Contains(TKey key) {
return base.Contains(_normalizeKey(key));
}
public new bool Contains(TItem item) {
return base.Contains(item);
}
//*---> Overrides
protected override TKey GetKeyForItem(TItem item) { return _normalizeKey(_getKeyFromItem(item)); }
protected override void InsertItem(int index, TItem item) {
base.InsertItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}
protected override void RemoveItem(int index) {
TItem item = this[index];
base.RemoveItem(index);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
}
protected override void SetItem(int index, TItem newItem) {
TItem item = this[index];
base.SetItem(index, newItem);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItem, index));
}
protected override void ClearItems() {
base.ClearItems();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
//*---> Raise CollectionChanged
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
var handler = CollectionChanged; if (handler == null) return;
handler(this, e);
}
}
//*---* *------------------------------------------------------*
///<summary>
/// Class KeysEqual is a generic equality comparer that is
/// used to determine equality of simple keys in the collection.
///</summary>
///<remarks>
/// Keys can be normalized here to represent equality from
/// an application point of view (e.g. strings are normalized
/// to InvariantCultureIgnoreCase if filenames are the key, etc.)
/// A Delegate can be specified to perform this task.
/// Remark
/// ------
/// This Delegate is also used to normalize TKeys in the
/// collection overrides.
///</remarks>
///
public class KeysEqual<TKey> : EqualityComparer<TKey> {
private Func<TKey, TKey> _normalizeKey;
internal Func<TKey, TKey> NormalizeKey { get { return _normalizeKey; } }
public KeysEqual() {_normalizeKey = (Func<TKey, TKey>)((s) => s);} //*---> (Func<string, string>)((s) => s.ToLowerInvariant());
public KeysEqual(Func<TKey, TKey> normalizeKey) { this._normalizeKey = normalizeKey; } // could be used for for simple strings to ignore caps
public override bool Equals(TKey x, TKey y) {
return _normalizeKey(x).Equals(_normalizeKey(y));
}
public override int GetHashCode(TKey key) {
return _normalizeKey(key).GetHashCode();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment