Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>ObservableCollection inherits from Collection, so it already has position-based indexing. </p> <p>For string-based indexing, you can look into peoples implementations of ObservableDictionary. </p> <p>Personally, for better performance, I've created a HashedObservableCollection deriving from ObservableCollection which contains a Dictionary of keys to indexes to speed lookup time. By overriding InsertItem, RemoveItem, and ClearItems, you keep the dictionary in sync.</p> <p>In my example, the keys can be of any type but we assume the key never changes - if an item is replaced, it is replaced with an object with the same key. If you want to simplify this, you can replace TKey with String.</p> <p>Code:</p> <pre><code>using System; using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; namespace foson.Utils { /// &lt;summary&gt; /// Represents BindableCollection indexed by a dictionary to improve lookup/replace performance. /// &lt;/summary&gt; /// &lt;remarks&gt; /// Assumes that the key will not change and is unique for each element in the collection. /// Collection is not thread-safe, so calls should be made single-threaded. /// &lt;/remarks&gt; /// &lt;typeparam name="TValue"&gt;The type of elements contained in the BindableCollection&lt;/typeparam&gt; /// &lt;typeparam name="TKey"&gt;The type of the indexing key&lt;/typeparam&gt; public class HashedBindableCollection&lt;TValue, TKey&gt; : ObservableCollection&lt;TValue&gt; { protected internal Dictionary&lt;TKey, int&gt; indecies = new Dictionary&lt;TKey, int&gt;(); protected internal Func&lt;TValue, TKey&gt; _keySelector; /// &lt;summary&gt; /// Create new HashedBindableCollection /// &lt;/summary&gt; /// &lt;param name="keySelector"&gt;Selector function to create key from value&lt;/param&gt; public HashedBindableCollection(Func&lt;TValue, TKey&gt; keySelector) : base() { if (keySelector == null) throw new ArgumentException("keySelector"); _keySelector = keySelector; } #region Protected Methods protected override void InsertItem(int index, TValue item) { var key = _keySelector(item); if (indecies.ContainsKey(key)) throw new DuplicateKeyException(key.ToString()); if (index != this.Count) { foreach (var k in indecies.Keys.Where(k =&gt; indecies[k] &gt;= index).ToList()) { indecies[k]++; } } base.InsertItem(index, item); indecies[key] = index; } protected override void ClearItems() { base.ClearItems(); indecies.Clear(); } protected override void RemoveItem(int index) { var item = this[index]; var key = _keySelector(item); base.RemoveItem(index); indecies.Remove(key); foreach (var k in indecies.Keys.Where(k =&gt; indecies[k] &gt; index).ToList()) { indecies[k]--; } } #endregion public virtual bool ContainsKey(TKey key) { return indecies.ContainsKey(key); } /// &lt;summary&gt; /// Gets or sets the element with the specified key. If setting a new value, new value must have same key. /// &lt;/summary&gt; /// &lt;param name="key"&gt;Key of element to replace&lt;/param&gt; /// &lt;returns&gt;&lt;/returns&gt; public virtual TValue this[TKey key] { get { return this[indecies[key]]; } set { //confirm key matches if (!_keySelector(value).Equals(key)) throw new InvalidOperationException("Key of new value does not match"); if (!indecies.ContainsKey(key)) { this.Add(value); } else { this[indecies[key]] = value; } } } /// &lt;summary&gt; /// Replaces element at given key with new value. New value must have same key. /// &lt;/summary&gt; /// &lt;param name="key"&gt;Key of element to replace&lt;/param&gt; /// &lt;param name="value"&gt;New value&lt;/param&gt; /// /// &lt;exception cref="InvalidOperationException"&gt;&lt;/exception&gt; /// &lt;returns&gt;False if key not found&lt;/returns&gt; public virtual bool Replace(TKey key, TValue value) { if (!indecies.ContainsKey(key)) return false; //confirm key matches if (!_keySelector(value).Equals(key)) throw new InvalidOperationException("Key of new value does not match"); this[indecies[key]] = value; return true; } public virtual bool Remove(TKey key) { if (!indecies.ContainsKey(key)) return false; this.RemoveAt(indecies[key]); return true; } } public class DuplicateKeyException : Exception { public string Key { get; private set; } public DuplicateKeyException(string key) : base("Attempted to insert duplicate key " + key + " in collection") { Key = key; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload