0
votes

I am facing an issue with dataGridView BindingContextChanged event firing. I have 2 datagridview in form and BindingContextChanged event implemented for both the grids.

On BindGrid method grid1 bound first with data source but BindingContextChanged event of grid2 fires first then grid1, then after grid2 bound with other data source but grid2 BindingContextChanged event does not fire. I have no clue why this is happening, I need each BindingContextChanged event should fire after respective grid data source assignment. Please help me to fix this issue.

below is the sample code

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        this.dataGridView1.BindingContextChanged += new System.EventHandler(this.dataGridView1_BindingContextChanged);
        this.dataGridView2.BindingContextChanged += new System.EventHandler(this.dataGridView2_BindingContextChanged);
    }

    private void btnBind_Click(object sender, EventArgs e)
    {
        BindGrid();
    }

    protected void BindGrid()
    {
        DataTable dt1 = new DataTable();
        dt1.Columns.Add("ID", typeof(int));
        dt1.Rows.Add(1);
        dt1.Rows.Add(2);
        dt1.Rows.Add(3);
        BindingSource dataSource = new BindingSource(dt1, null);
        dataGridView1.DataSource = dataSource;

        DataTable dt = new DataTable();
        dt.Columns.Add("ID", typeof(int));
        dt.Rows.Add(1);
        dt.Rows.Add(2);
        dt.Rows.Add(3);

        BindingSource dataSource1 = new BindingSource(dt, null);
        dataGridView2.DataSource = dataSource1;
       
    }

    private void dataGridView1_BindingContextChanged(object sender, EventArgs e)
    {
        // Continue only if the data source has been set.
        if (dataGridView1.DataSource == null)
        {
            return;
        }
    }

    private void dataGridView2_BindingContextChanged(object sender, EventArgs e)
    {
        // Continue only if the data source has been set.
        if (dataGridView2.DataSource == null)
        {
            return;
        }

    }

   
}
1
The BindingContextChanged is raised multiple times, either when you first create a DataGridView (when its Handle is created) or when any Control in a Form sets a DataSource. The sequence of the events is related to the order in which Controls are added to a Container. Check in the .Designer.cs file of your Form: this.Controls.Add(this.dataGridView1); is probably inserted after this.Controls.Add(this.dataGridView2);. So, just invert it. -- Why are you handling this event? As mentioned, any other Control can cause it to raise. What is it for? - Jimi
thanks @Jimi, I am trying to implement DataGridViewAutoFilter where my grid is having autogenerated columns and having more than one grid in form all required auto filter enabled, as BindingContextChanged event renders the auto filter columns my second grid unable to render as its event never get fired after databinding. This is the sample code I am using from Microsoft site microsoft.com/en-us/download/details.aspx?id=23459 - Neeraj Kumar Gupta
First thing, the event is raised for both Controls and, as mentioned, in the order defined in the Form's Designer. But, you probably don't need it. See How to replace the HeaderCells of a DataGridView with custom headers?. This can be done when required. Would you also reset the Headers if an unrelated Control, e.g., ComboBox, resets the BindingContext for some reason? -- Note that the example you're referring to, if it is what I think it is, is very, very old. Update the .Net version to at least .Net Framework 4.8. - Jimi

1 Answers

0
votes

I was able to reproduce this problem. I changed from BindingContextChanged event handlers to DataSourceChanged, and that solved the issue. E.g.

this.dataGridView1.BindingContextChanged += new System.EventHandler(this.dataGridView1_BindingContextChanged);
this.dataGridView2.BindingContextChanged += new System.EventHandler(this.dataGridView2_BindingContextChanged);

to...

this.dataGridView1.DataSourceChanged += new System.EventHandler(this.dataGridView1_DataSourceChanged);
this.dataGridView2.DataSourceChanged += new System.EventHandler(this.dataGridView2_DataSourceChanged);

Now dataGridView1.DataSource isn't null when the event fires, and each fires according with the modified binding source.