Friday, September 18, 2009

Keeping DataGrids And Other UI Controls In Sync

Have you ever noticed that sometimes your databound WinForm controls don't seem to want to stay in sync? Most likely you have a problem with the way you're databinding the controls. This is pretty elementary and basic stuff, but you may be surprised at how often I see questions about this very thing.

There are two ways (two different syntaxes) to specify databinding for any control and this results in two distinct binding objects. The problem is that you can't mix and match ... you have to stay consistent throughout the form.

Here are examples of the two different syntaxes:

// If you bound your DataGrid with:
this.oGrid.DataSource = MyDataSet;
this.oGrid.DataMember = "MyTable";

// Then you have to use the following syntax with TextBoxes:
this.txtLastName.DataBindings.Add("Text", MyDataSet, "MyTable.LastName");


//But if you bound your grid with:
this.oGrid.DataSource = MyDataSet.Tables["MyTable"];

//Then you use this syntax for TextBoxes:
this.txtLastName.DataBindings.Add("Text", MyDataSet.Tables["MyTable"], "LastName");

Personally, I prefer the second syntax and use it religiously.

UPDATE: I should also talk about using a BindingSource:

If you’re using a BindingSource, then you won’t have this problem at all, because then you are using the exact same binding object with no way to screw it up!

You could still setup a BindingSource with either syntax:

BindingSource bsMyTable = new BindingSource();

// First syntax:
this.bsMyTable.DataSource = MyDataSet;
this.bsMyTable.DataMember = "MyTable";

// Second syntax:
this.bsMyTable.DataSource = MyDataSet.Tables["MyTable"];

// If you're using Typed DataSets, that second syntax becomes:
this.bsMyTable.DataSource = MyDataSet.MyTable

As before, I prefer the second syntax. And, if you are using Typed DataSets (which I do), the second syntax is even more important since there’s less of a chance of a typo screwing things up.

// And the binding for the two controls will always be the same!
this.oGrid.DataSource = this.bsMyTable;
this.txtLastName.DataBindings.Add("Text", this.bsMyTable, "LastName");

It’s much easier and cleaner, I think, to use a BindingSource!

2 comments:

  1. how about this ?

    // starts here
    DataTable dt = new DataTable();
    dt = MyDataSet.Tables["MyTable"];
    this.oGrid.DataSource = dt;
    // then use this syntax for TextBoxes
    this.txtLastName.DataBindings.Add("Text",dt,"LastName");
    // end here

    I do not like "DataMember" because in my point of view a dataset is easier to understand as "a set of related table(s)".
    is there any performance cost ? thank you ...

    ReplyDelete
    Replies
    1. Bayu -- that's pretty much the same thing that I showed in my second example (and that's the way I prefer to do it also; not using "DataMember" as shown in my first example).

      The only difference between what you posted and what I posted is that you set up a separate variable, dt, to hold the instance of MyDataSet.Tables["MyTable"]. That is only for easier readability of the DataBinding statements and is perfectly OK to do (I do that myself frequently ... readability is important!). However, you don't need to create the DataTable first. Do it like this:

      DataTable dt = MyDataSet.Tables["MyTable"];

      Delete