I'm trying to create a Bindable FlowLayoutPanel that can take a DataSource and map it the specified generic parameter <T> controls.  Only minimal requirements are to have a selectable index and to be able to change the background color of the selected and deselected controls.  I've tried to leave out the implementation of the selected index except for obvious cases.  This leaves the option to the developer as to how to move the selected index when a control is added/removed/etc.  I have an example program that uses the below and it seems to work ok (it's not very large, but too big to post here).I was hoping someone else could take a look at this and see if there are any obvious issues.using System;using System.ComponentModel;using System.Drawing;using System.Windows.Forms;using System.Drawing.Design;namespace DataBindingListOfUserControls{   /// <summary>   /// Create a Bindable FlowLayoutPanel   /// </summary>   /// <typeparam name=T>The control type that will be in the FlowLayoutPanel</typeparam>   /// <remarks>Note!!! If you wish to use this in a designer, you must create a class   /// that does not use or derive from this generic class.  For example, doing something   /// like: BindableFlowLayoutPanel[MyCtrl] would give you designer errors.  To fix this,   /// you need to create a class that does not derive from the generic class.  So you   /// would do this: class MyCtrlBflp : MiddleBflp,    /// then class MiddleBflp : BindableFlowLayoutPanel[MyCtrl]  Then you would use   /// MyCtrlBflp from the Toolbox (and you can create an instance of this through the   /// designer)</remarks>   public partial class BindableFlowLayoutPanel<T> : UserControl, INotifyPropertyChanged       where T : Control, IBindableObject, new()   {      #region Constants      /// <summary>      /// The constant value if no control is selected      /// </summary>      private const int NO_SELECTED_INDEX = -1;      #endregion      #region Member Variables      /// <summary>      /// The data source that will bind to the controls      /// </summary>      private BindingSource mDataSource = null;      /// <summary>      /// The deselected background color of the controls      /// </summary>      private Color mDeselectedControlColor = SystemColors.Control;      /// <summary>      /// The selected background color of the controls      /// </summary>      private Color mSelectetedControlColor = SystemColors.GradientInactiveCaption;      /// <summary>      /// The selected control within the FlowLayoutPanel      /// Let the model control this so you can implement your own desired      /// navigation when items are added, removed, inserted, etc      /// </summary>      private int mSelectedIndex = NO_SELECTED_INDEX;      #endregion      #region Constructor      /// <summary>      /// Creates an instance of the Bindable FlowLayoutPanel      /// </summary>      public BindableFlowLayoutPanel()      {         InitializeComponent();      }      #endregion      #region Properties      /// <summary>      /// Set the data source that will bind to the controls in the FlowLayoutPanel      /// </summary>      /// <param name=bindingSource>The binding source</param>      [TypeConverter(System.Windows.Forms.Design.DataSourceConverter, System.Design)]      [Editor(System.Windows.Forms.Design.DataSourceListEditor,          System.Design, typeof(UITypeEditor))]      [AttributeProvider(typeof(IListSource))]      [DefaultValue(null)]      public object DataSource      {         set         {            // Only change if its different            if (mDataSource != value)            {               // Unregister the events if we were already bound to a source               CleanUpDataSource();               // Check to make sure the object is a data source               BindingSource new_binding_source = value as BindingSource;               if ((value != null) && (new_binding_source == null))               {                  throw new ArgumentException(DataSource must be a BindingSource);               }               // Setup the binding source to listen for list changes and Enter event               // listeners for each control               mDataSource = new_binding_source;               if (mDataSource != null)               {                  mDataSource.ListChanged +=                      new ListChangedEventHandler(DataSourceListChangedEventHandler);                  for (int i = 0; i < mDataSource.Count; i++)                  {                     AddControl(i);                  }               }            }         }      }      /// <summary>      /// Get/Set the deselected background color of the controls      /// </summary>      public Color DeselectedControlColor      {         get         {            return mDeselectedControlColor;         }         set         {            mDeselectedControlColor = value;         }      }      /// <summary>      /// Get/Set the selected background color of the controls      /// </summary>      public Color SelectetedControlColor      {         get         {            return mSelectetedControlColor;         }         set         {            mSelectetedControlColor = value;         }      }      /// <summary>      /// Get/Set the currently selected control index      /// Make this bindable and let the outside world control      /// how this is updated      /// <remarks>The selected index will be internally set to      /// -1 if the selected index is removed or if a control      /// is attempted to be selected but fails</remarks>      /// </summary>      [System.ComponentModel.Bindable(true)]       public int SelectedIndex      {         get         {            return mSelectedIndex;         }         set         {            if (mSelectedIndex != value)            {               // Clear the currently selected control               ClearSelectedControl();               mSelectedIndex = value;               // Set the selected control               if (SetSelectedControl(value))               {                  // Notify this change since its custom                  NotifyPropertyChanged(SelectedIndex);               }               else               {                  // Dont notify the reset and set internally as not set                  mSelectedIndex = NO_SELECTED_INDEX;               }            }         }      }      #endregion      #region Functions      /// <summary>      /// Add a new control at the specified index      /// </summary>      /// <param name=indexOfControl>The index to add/insert the new      /// control</param>      private void AddControl(int indexOfControl)      {         // Create a new control         T new_control = new T();         // Setup the bindings from the UI to the data source         new_control.BindingObject = mDataSource[indexOfControl];         // Keep track of when the control is entered         new_control.Enter += new EventHandler(ControlEnteredEventHandler);         // Update the background color         new_control.BackColor =            (SelectedIndex == indexOfControl) ?                SelectetedControlColor : DeselectedControlColor;         // Add the new control to the end (no insert option, so add to end         // and then set the child index)         mFlowLayoutPanel.Controls.Add(new_control);         // Change the location of the control to the index desired         mFlowLayoutPanel.Controls.SetChildIndex(new_control, indexOfControl);      }      /// <summary>      /// Remove listeners from the data source and from the individual controls      /// Also call on Dispose      /// </summary>      private void CleanUpDataSource()      {         if (mDataSource != null)         {            // Unregister for list change events and remove the Enter event            // listeners for each control            mDataSource.ListChanged -=                new ListChangedEventHandler(DataSourceListChangedEventHandler);            while (mFlowLayoutPanel.Controls.Count > 0)            {               RemoveControl(0);            }            // No selected controls            SelectedIndex = NO_SELECTED_INDEX;         }      }      /// <summary>      /// Clear the selected control (Change background color to deselected)      /// </summary>      private void ClearSelectedControl()      {         if (SelectedIndex != NO_SELECTED_INDEX)         {            T last_ui_control_selected = GetControl(SelectedIndex);            if (last_ui_control_selected != null)            {               last_ui_control_selected.BackColor = DeselectedControlColor;            }         }      }      /// <summary>      /// Get the control at the specified index from the FlowLayoutPanel      /// </summary>      /// <param name=indexOfControl>The index of the control to get</param>      /// <returns>The control at the specified index.  null if the control does      /// not exist</returns>      private T GetControl(int indexOfControl)      {         // Make sure the index is valid, otherwise return null         if (indexOfControl >= mFlowLayoutPanel.Controls.Count)         {            return null;         }         return mFlowLayoutPanel.Controls[indexOfControl] as T;      }      /// <summary>      /// Fire the property changed event with the specified property name      /// </summary>      /// <param name=propName>The property name that was updated</param>      private void NotifyPropertyChanged(String propName)      {         PropertyChangedEventHandler prop_changed = PropertyChanged;         if (prop_changed != null)         {            prop_changed(this, new PropertyChangedEventArgs(propName));         }      }      /// <summary>      /// Remove the control at the specified index      /// </summary>      /// <param name=indexOfControl>The index of the control to remove      /// from the FlowLayoutPanel</param>      private void RemoveControl(int indexOfControl)      {         // Get the control to remove from the FlowLayoutPanel         T control_to_remove = mFlowLayoutPanel.Controls[indexOfControl] as T;         // Unregister the Enter event         control_to_remove.Enter -= new EventHandler(ControlEnteredEventHandler);         control_to_remove.BindingObject = null;         // Remove the control from the FlowLayoutPanel         mFlowLayoutPanel.Controls.Remove(control_to_remove);         if (mSelectedIndex == indexOfControl)         {            // Internally clear the selected because the control was removed            mSelectedIndex = NO_SELECTED_INDEX;         }      }      /// <summary>      /// Set the specified control as selected      /// </summary>      /// <param name=indexOfControl>The index of the control      /// in the FlowLayoutPanel</param>      /// <returns>True if the control was selected, False otherwise</returns>      private bool SetSelectedControl(int indexOfControl)      {         if (indexOfControl >= 0)         {            T control_to_select = GetControl(indexOfControl);            if (control_to_select != null)            {               control_to_select.Select();               control_to_select.BackColor = SelectetedControlColor;               mFlowLayoutPanel.ScrollControlIntoView(control_to_select);               return true;            }         }         return false;      }      #endregion      #region Event Handlers      /// <summary>      /// Handle when a control in the FlowLayoutPanel is entered      /// </summary>      /// <param name=sender>The control that fired the event</param>      /// <param name=e>The event arguments</param>      private void ControlEnteredEventHandler(object sender, EventArgs e)      {         // Keep track of the currently selected index since this could be user fired         SelectedIndex = mFlowLayoutPanel.Controls.IndexOf(sender as Control);      }      /// <summary>      /// Handle when the data source has changed.  Update the UI accordingly      /// </summary>      /// <param name=sender>The control that fired the event</param>      /// <param name=e>The event arguments</param>      private void DataSourceListChangedEventHandler(object sender, ListChangedEventArgs e)      {         if (e.ListChangedType == ListChangedType.ItemAdded)         {            // Add the new control to the UI at the end that maps to the new model added            AddControl(e.NewIndex);         }         else if (e.ListChangedType == ListChangedType.ItemDeleted)         {            // Make sure the new index is ok to be deleted            if (mFlowLayoutPanel.Controls.Count > e.NewIndex)            {               // Remove the control from the UI at the specified index               RemoveControl(e.NewIndex);            }         }      }      #endregion      #region INotifyPropertyChanged Members      /// <summary>      /// The Property Changed event      /// </summary>      public event PropertyChangedEventHandler PropertyChanged;      #endregion   } // BindableFlowLayoutPanel} // DataBindingListOfUserControlsHere is the IBindableObject definition:public interface IBindableObject{   object BindingObject { set; }}
Binding FlowLayoutPanel
c#;winforms
Turns out I was going about this the wrong way.  I updated this to use the CurrencyManager class instead to manage the bindings for me.  This was a much better solution.