C# BindingDictionary(of T) Implementation
<h3>Summary</h3>

<ul>
<li>A while back I decided to use a BindingList to hookup to a datasource and receive automatic updates from an incoming service (and have my datagrid refresh at the same time).</li>
<li>What I started to realise was how much more efficient it would be for me (in terms of accessing data easily), to have a BindingDictionary instead that had EXACTLY the same functionality.</li>
<li>I ended up implementing the below code, which works perfectly for updates.....</li>
<li>...<strong>BUT</strong>...fails miserably when the BindingDictionary is already bound to my datagrid and I try and add a new object to it (The new object never appears).</li>
<li>I know I've missed some of the implementation out somewhere.....</li>
</ul>

<h3>...Can Anyone Help Me Finish The Implementation?</h3>

<pre><code> [Serializable]
[XmlRoot("dictionary")]
[KnownType(typeof(BindableDictionary&lt;string, string&gt;))]
public class BindableDictionary&lt;TKey, TValue&gt; : IDictionary&lt;TKey, TValue&gt;, IBindingList, IXmlSerializable
{
    #region Serialize Stuff

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    #region READ XML

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");
            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();
            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();
            this.Add(key, value);
            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    #endregion READ XML

    #region WRITE XML

    public void WriteXml(System.Xml.XmlWriter writer)
    {

        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");
            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();
            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    }

    #endregion WRITE XML

    #endregion Serialize Stuff

    private Dictionary&lt;TKey, TValue&gt; source = new Dictionary&lt;TKey, TValue&gt;();
    private Dictionary&lt;int, TKey&gt; sourceKey = new Dictionary&lt;int, TKey&gt;();

    void IBindingList.AddIndex(PropertyDescriptor property) { }
    object IBindingList.AddNew() { throw new NotImplementedException(); }
    bool IBindingList.AllowEdit { get { return true; } }
    bool IBindingList.AllowNew { get { return false; } }
    bool IBindingList.AllowRemove { get { return false; } }
    void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { }
    int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotImplementedException(); }
    bool IBindingList.IsSorted { get { return false; } }
    void IBindingList.RemoveIndex(PropertyDescriptor property) { }
    void IBindingList.RemoveSort() { }
    ListSortDirection IBindingList.SortDirection { get { return ListSortDirection.Ascending; } }
    PropertyDescriptor IBindingList.SortProperty { get { return null; } }
    bool IBindingList.SupportsChangeNotification { get { return true; } }
    bool IBindingList.SupportsSearching { get { return false; } }
    bool IBindingList.SupportsSorting { get { return false; } }
    int System.Collections.IList.Add(object value) { throw new NotImplementedException(); }
    void System.Collections.IList.Clear() { Clear(); }
    bool System.Collections.IList.Contains(object value) { if (value is TKey) { return source.ContainsKey((TKey)value); } else if (value is TValue) { return source.ContainsValue((TValue)value); } return false; }
    int System.Collections.IList.IndexOf(object value) { return -1; }
    void System.Collections.IList.Insert(int index, object value) { throw new NotImplementedException(); }
    bool System.Collections.IList.IsFixedSize { get { return false; } }
    bool System.Collections.IList.IsReadOnly { get { return true; } }
    void System.Collections.IList.Remove(object value) { if (value is TKey) { Remove((TKey)value); } }
    void System.Collections.IList.RemoveAt(int index) { throw new NotImplementedException(); }

    object System.Collections.IList.this[int index]
    {
        get
        {
            return source[sourceKey[index]];
        }
        set { throw new NotImplementedException(); }
    }

    private ListChangedEventHandler listChanged;

    event ListChangedEventHandler IBindingList.ListChanged
    {
        add { listChanged += value; }
        remove { listChanged -= value; }
    }

    protected virtual void OnListChanged(ListChangedEventArgs e)
    {
        var evt = listChanged;

        if (evt != null) evt(this, e);
    }

    public void Add(TKey key, TValue value)
    {
        source.Add(key, value);
        sourceKey.Add(sourceKey.Count, key);
        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    public bool Remove(TKey key)
    {
        if (source.Remove(key))
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

            return true;
        }

        return false;
    }

    public TValue this[TKey key]
    {
        get
        {
            return source[key];
        }
        set
        {
            source[key] = value;

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
    }

    void ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.Add(KeyValuePair&lt;TKey, TValue&gt; item)
    {
        ((ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;)source).Add(item);

        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    bool ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.Remove(KeyValuePair&lt;TKey, TValue&gt; item)
    {
        if (((ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;)source).Remove(item))
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

            return true;
        }

        return false;
    }

    public bool ContainsKey(TKey key) { return source.ContainsKey(key); }
    public ICollection&lt;TKey&gt; Keys { get { return source.Keys; } }
    public bool TryGetValue(TKey key, out TValue value) { return source.TryGetValue(key, out value); }
    public ICollection&lt;TValue&gt; Values { get { return source.Values; } }
    public void Clear() { source.Clear(); }
    bool ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.Contains(KeyValuePair&lt;TKey, TValue&gt; item) { return ((ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;)source).Contains(item); }
    void ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.CopyTo(KeyValuePair&lt;TKey, TValue&gt;[] array, int arrayIndex) { ((ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;)source).CopyTo(array, arrayIndex); }
    public int Count { get { return source.Count; } }
    bool ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.IsReadOnly { get { return ((ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;)source).IsReadOnly; } }
    public IEnumerator&lt;KeyValuePair&lt;TKey, TValue&gt;&gt; GetEnumerator() { return source.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
    bool ICollection.IsSynchronized { get { return false; } }
    object ICollection.SyncRoot { get { return null; } }
    void ICollection.CopyTo(Array array, int arrayIndex) { ((ICollection)source).CopyTo(array, arrayIndex); }
}
</code></pre>
