C# – WinForms DataBinding with DataGridView

cdata-bindingdatagridviewwinforms

I though I would post this as after spending several hours trying to work it out I am getting nowhere. Firstly, I am fully aware that databinding in WinForms is not the best. That said it does work in most scenarios.

In my scenario, I have a binding source which is the master for my form. The object that is used for this binding source has a few simple properties and two binding lists as properties as well. Both this class, and the class type for the binding lists implement INotifyPropertyChanged. On my form, I have two DataGridViews for displaying the contents of the binding list properties.

This is also done through databinding at design time. I have two binding sources for each which use the main binding source as there data source and then the respective bindinglist properties as the data member.

So far, I would consider this to be fairly standard.

To update what is in these lists I have buttons to show a form that creates a new item, which I then add to the lists using BindingList.Add().

Now in code, if you debug, the items are in the lists, however, the grids are not updating.
But if I add a listbox to the form which uses just one of the list binding sources then both of the grids start refreshing as expected.

I apologise if any of this is unclear, I have tried to explain as best as I can with a confusing situation.

Any thoughts would be helpful as I really don't want to have to use a hidden list box.

Best Answer

This code works fine for me

BindingList<Foo> source; // = ...
private void Form1_Load(object sender, EventArgs e)
{
    this.dataGridView1.DataSource = new BindingSource { DataSource = source };
    this.dataGridView2.DataSource = new BindingSource { DataSource = source, DataMember = "Children" };
}

private void button1_Click(object sender, EventArgs e)
{
    source.Add(new Foo { X = Guid.NewGuid().ToString() });
}

private void button2_Click(object sender, EventArgs e)
{
    source[0].Children.Add(new FooChild { Y = Guid.NewGuid().ToString() });
}

with the model

public class Foo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    string x;
    public string X
    {
        get { return x; }
        set
        {
            x = value;
            this.NotifyPropertyChanged();
        }
    }

    BindingList<FooChild> children;
    public BindingList<FooChild> Children
    {
        get { return children; }
        set
        {
            children = value;
            this.NotifyPropertyChanged();
        }
    }
}

public class FooChild : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    string y;
    public string Y
    {
        get { return y; }
        set
        {
            y = value;
            this.NotifyPropertyChanged();
        }
    }
}

Both grids get refreshed.

I hope this helps you

Edit

I changed the Form1_Load impl