title: C# WCF - Sending Custom BindableDictionary<string,CustomObject>() Over The Wire
body: <h3>EDIT</h3>
  <ul>
  <li>Ok, I've got it, it's not serializable.........so, how do I go about serializing it?</li>
  </ul>
  <h3>Scenario</h3>
  <ol>
  <li>I have a custom BindableDictionary
  that I use to bind with a grid
  control for automatically updating
  the grid when the underlying
  datasource changes.</li>
  <li>I now want to extend my application
  to use WCF, so that when the
  server-side has finished updating
  the BindableDictionary with new
  values, it can pass this dictionary
  to the client, which in turn can
  perform the update on the Client
  GUI.</li>
  </ol>
  <h3>Problem</h3>
  <ul>
  <li>How do I go about sending this custom
  BindableDictionary over the wire?</li>
  <li>What is the best way to implement this?</li>
  <li>The reason I ask about an implementation method is that every example I've seen of Duplex, Callbacks or the Observer Pattern for &quot;PUSHING&quot; my data to the client, only uses an example of passing strings, and it's very primitive - Whenever I update the examples to use my custom BindableDictionary, I cannot get it to work.</li>
  <li>Am I missing something?</li>
  </ul>
  <h3>BindableDictionary</h3>
  <pre><code>    public class BindableDictionary&lt;TKey, TValue&gt; : IDictionary&lt;TKey, TValue&gt;, IBindingList
      {
          private Dictionary&lt;TKey, TValue&gt; source = new Dictionary&lt;TKey, TValue&gt;();
  
          void IBindingList.AddIndex(PropertyDescriptor property) { }
          object IBindingList.AddNew() { throw new NotImplementedException(); }
          bool IBindingList.AllowEdit { get { return false; } }
          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 { throw new NotImplementedException(); } 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);
  
              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>