title: WPF: Implementing and binding (datagrid) to a custom collection
body: <p>I have a custom collection that I am passing to a WPF client, which is binding the collection to a <code>datagrid</code> using <code>AutoGenerateColumns="True"</code>. The datagrid, however, is displaying empty rows (albeit the right number of empty rows). What am I doing wrong? Following is some sample code. For now I've omitted everything having to do with <code>INotifyPropertyChanged</code> and <code>INotifyCollectionChanged</code> because, well, I first want to have some data showing up in the grid.</p>
  
  <p>I should also mention that I've tried implementing the above two interfaces, but they seem to have nothing to do with this issue.</p>
  
  <p>(You might not actually want to look at the sample code as there's absolutely nothing interesting about it. The collection implementation is just wrapping an inner List.)</p>
  
  <p>Some random POCO:</p>
  
  <pre><code>public class Person
  {
      public string FirstName { get; set; }
      public string LastName { get; set; }
  }
  </code></pre>
  
  <p>Simple collection implementation:</p>
  
  <pre><code>public class MyCollection&lt;T&gt; : IList&lt;T&gt;
  {
      private List&lt;T&gt; list = new List&lt;T&gt;();
  
      public MyCollection()
      {
      }
  
      public MyCollection(IEnumerable&lt;T&gt; collection)
      {
          list.AddRange(collection);
      }
  
   #region ICollection&lt;T&gt; Members
  
      public void Add(T item)
      {
         list.Add(item);
      }
  
      public void Clear()
      {
         list.Clear();
      }
  
      public bool Contains(T item)
      {
          return list.Contains(item);
      }
  
      public void CopyTo(T[] array, int arrayIndex)
      {
         list.CopyTo(array, arrayIndex);
      }
  
      public int Count
      {
         get { return list.Count; }
      }
  
      public bool IsReadOnly
      {
          get { return false; }
      }
  
      public bool Remove(T item)
      {
         return list.Remove(item);
      }
  
  #endregion
  
  #region IEnumerable&lt;T&gt; Members
  
      public IEnumerator&lt;T&gt; GetEnumerator()
      {
          return list.GetEnumerator();
      }
  
  #endregion
  
  #region IEnumerable Members
  
      System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
      {
          return GetEnumerator();
      }
  
  #endregion
  
  #region IList&lt;T&gt; Members
  
      public int IndexOf(T item)
      {
          return list.IndexOf(item);
      }
  
      public void Insert(int index, T item)
      {
         list.Insert(index, item);
      }
  
      public void RemoveAt(int index)
      {
         list.RemoveAt(index);
      }
  
      public T this[int index]
      {
         get { return list[index]; }
         set { list[index] = value; }
      }
  
     #endregion
  } 
  </code></pre>
  
  <p>The XAML:</p>
  
  <pre><code>&lt;Window x:Class="TestWpfCustomCollection.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="MainWindow" Height="350" Width="525"&gt;
      &lt;Grid&gt;
          &lt;DataGrid AutoGenerateColumns="True" 
                    HorizontalAlignment="Stretch" 
                    Name="dataGrid1" VerticalAlignment="Stretch" 
                    ItemsSource="{Binding}" 
          /&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>The window's code-behind:</p>
  
  <pre><code>public MainWindow()
  {
       InitializeComponent();
  
       MyCollection&lt;Person&gt; persons = new MyCollection&lt;Person&gt;()
       {
           new Person(){FirstName="john", LastName="smith"},
           new Person(){FirstName="foo", LastName="bar"}
       };
  
       dataGrid1.DataContext = persons;
  }
  </code></pre>
  
  <p>By the way, if you change the code-behind to use a List&lt;Person> instead of the MyCollection&lt;Person>, everything works as expected.</p>
  
  <p>EDIT:</p>
  
  <p>The above code is not taken from the real situation. I have only posted it to show what I am doing in order to test my problem and to make it easier to replicate it. <strong>The actual custom collection object is quite complex and I cannot post it here</strong>. Again, I'm just trying to understand the basic concept behind what needs to be done in order for a datagrid to properly bind to a custom collection and automatically generate columns for the underlying objects.</p>