title: BindingList vs List - WinForms Data Binding
body: <p>In order to get data binding in WinForms (to a DataGridView, for instance) to work anything like you'd hope and add/delete rows as the collection changes, you have to use a BindingList (or DataTable) instead of a generic List.  The problem is, almost nobody has the first instinct to code with a BindingList instead of a List in their libraries.</p>
  
  <p>The BindingList implements two events that the List doesn't have and these must be the difference in data binding action (also, a property to suppress the second event):</p>
  
  <pre><code>AddingNew
  ListChanged
  RaiseListChangedEvents
  </code></pre>
  
  <p>Similarly, the DataTable has two events which probably enable similar functionality:</p>
  
  <pre><code>RowDeleted
  TableNewRow
  </code></pre>
  
  <p><strong>EDIT</strong>: As the helpful SO community pointed out here <a href="https://stackoverflow.com/questions/20398832/convert-generic-list-to-bindinglistt">and in another article</a>, a List can be converted (maybe more accurately encapsulated?) by calling the correct BindingList constructor:</p>
  
  <pre><code>BindingList&lt;MyType&gt; MyBL = new BindingList&lt;MyType&gt;();
  MyList.ForEach(x =&gt; MyBL.Add(x));
  </code></pre>
  
  <p>My situation is a little more complicated as illustrated by the code below.
  <strong>EDIT</strong> Added INotifyPropertyChanged stuff that must exist in the real library.</p>
  
  <pre><code>public class RealString : INotifyPropertyChanged
  {
    private int _KnotCount = 0;
    private List&lt;KnotSpace&gt; _KnotSpacings = new List&lt;KnotSpace&gt;();
  
    public RealString()
    {
      KnotSpacings.Add(new KnotSpace());
    }
  
    public int KnotCount
    {
      get { return _KnotCount; }
  
      set
      {
        int requiredSpacings = 0;
  
        _KnotCount = value;
        // Always one more space than knots
        requiredSpacings = _KnotCount + 1;
  
        if (requiredSpacings &lt; KnotSpacings.Count)
        {
          while (requiredSpacings &lt; KnotSpacings.Count)
          {
            KnotSpacings.Add(new KnotSpace());
          }
        }
        else if (requiredSpacings &gt; KnotSpacings.Count)
        {
          while (requiredSpacings &gt; KnotSpacings.Count)
          {
            KnotSpacings.Remove(KnotSpacings.Last());
          }
        }
        this.OnPropertyChanged(this, "KnotCount");
      }
  
    }
  
    public List&lt;KnotSpace&gt; KnotSpacings { get =&gt; _KnotSpacings; }
  
    public event PropertyChangedEventHandler PropertyChanged;
  
    protected virtual void OnPropertyChanged(object sender, string PropertyName)
    {
      if (this.PropertyChanged == null) return;
      this.PropertyChanged(sender, new PropertyChangedEventArgs(PropertyName));
    }
  
  }
  
  public class KnotSpace
  {
    private double _Spacing = 10;
  
    public double Spacing { get =&gt; _Spacing; set =&gt; _Spacing = value; }
  
  }
  </code></pre>
  
  <p>The things in the list are displayed in the UI, and the properties of the things in the list are modified in the UI, but the UI doesn't directly add/remove things from the list except by changing the KnotCount property.  Wrapping the KnotSpacings property in a BindingList doesn't result in the BindingList updating when KnotSpacings is updated by changing the KnotCount property.</p>
  
  <p><strong>EDIT</strong> OK, more clarification...</p>
  
  <pre><code>BindingList BL = new BindingList&lt;KnotSpace&gt;(MyRealString.KnotSpacings);
  
  DataGridView1.AutoGenerateColumns = true;
  DataGridView1.DataSource = BL;
  NumericUpDown1.DataBindings.Add("Value", MyRealString, "KnotCount", false, DataSourceUpdateMode.OnPropertyChanged);
  </code></pre>
  
  <p>The BindingList has no more success tracking the changes to the underlying List property (KnotSpacings) than the Windows controls.  So data binding the controls to the BindingList doesn't accomplish much.  BindingList works great if UI adds/removes items from the BindingList because it does the same operations in the underlying List.  But then I would need to replicate the add/remove action and logic of the library in my UI and that's a breaking change in waiting.</p>
  
  <p><strong>EDIT</strong> Major changes made to my original post attempting to: (1) Clarify the problem. (2) Distinguish it as not a duplicate question (although one of the several questions was a dup). (3) Acknowledge the helpful efforts of others that would be lost if I deleted the post.</p>