Search code examples
c#data-bindingnestedparent-childbindingsource

C# nested bindingsource parent-children relation


To make my problem easier to understand let's assume we have a form having 2 combo-boxes (parent combo and child combo). When you select the parent combobox the child combobox's items change accordingly. State County is a good example.

Below is the data model.

public class item
{
    public string childname { get; set; }
    public item(string n) { childname = n; }
}

public class itemparent
{
    public BindingSource<item> Children { get; set; }

    public string parentName { get; set; }

    public itemparent(string parentname,item n)
    {
        Children = new BindingSource<item>();

        this.parentName = parentname;
    }
}


public class BindingSource<T> : BindingSource
{
    public new T Current
    {
        get
        {
            return (T)base.Current;
        }
    }
}

And below is how i bind them.

        public BindingSource<itemparent> bsource { get; set; }
    private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
            this.bsource = new BindingSource<itemparent>()
            {
                new itemparent("parent Henry",new item("child name Marry")) ,
                new itemparent("parent Todd",new item("child name Alex")) 
            };

            //this works fine
            var bnd = new Binding("DataSource", this, "bsource");
            this.combo_parents.DataBindings.Add(bnd);
            this.combo_parents.DisplayMember = "parentName";

             //not working as i expect it, does not uplate data source if the above combo changes
            //and i cannot bind to bsource.Children.Current (throws exception complaining that Current prop no found)
            combo_children.DataBindings.Add("DataSource", this, "bsource.Children");
            combo_children.DisplayMember = "childname";

        }
        catch (Exception ex)
        {
            Debugger.Break();
        }
    }
}

I want to use the bindingsource.current for children also and be able to do:

 Get Selected Parent Item
 bsource.Current
 Get Selected Child item
 bsource.Current.Children.Current

I know that there are other ways to do it but i find this way to be the cleanest. Do the bindings then at any point using the BindingSource you can get the selected item. Full VStudio solution of this tryout is available here.


Solution

  • Interesting idea. But you need to account one detail - you cannot bind to a property of a object that is list. So you need to change slightly your design.

    First, the custom binding source class should not inherit the BindingSource, but have a BindingSource property like this

    public class BindingSource<T>
    {
        public BindingSource() { Source = new BindingSource(); }
        public BindingSource Source { get; set; }
        public T Current { get { return (T)Source.Current; } }
        public event EventHandler CurrentChanged
        {
            add { Source.CurrentChanged += value; }
            remove { Source.CurrentChanged -= value; }
        }
    }
    

    Then the binding would be like this

    public BindingSource<itemparent> bsource { get; set; }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        this.bsource = new BindingSource<itemparent>
        {
            Source = new BindingSource
            {
                new itemparent("parent Henry",new item("child name Marry")) ,
                new itemparent("parent Todd",new item("child name Alex"))
            }
        };
    
        this.combo_parents.DataBindings.Add("DataSource", this, "bsource.Source");
        this.combo_parents.DisplayMember = "parentName";
    
        this.combo_children.DataBindings.Add("DataSource", this, "bsource.Current.Children.Source");
        this.combo_children.DisplayMember = "childname";
    }