TIP: Managing BindingSource Position in Data Driven WinForms
Posted by Keith Elder | Posted in .Net, Programming, Smart Clients | Posted on 28-06-2006
12
If you are working with a Windows Form where a user can create and edit data in the same form you may run into the problem of trying to set the BindingSource to a given record in a DataSet you want to work with.
For example let’s say you have a DataGridView in a Smart Client. When the user double clicks a given row in the DataGridView a form opens so they can edit the data. More times than not (no matter how many demos you watch) user’s do not edit data values in DataGridViews. Although this is a supported feature, business objects are too complex. Imagine having to edit a contact in a single row in Outlook for example, not fun and not very user friendly. Why every Microsoft demo I watch shows editing in DataGridViews is beyond me. I digress though.
When the new form is instantiated we need to pass two things: the dataset we are working with, and the IDof the item we want to edit. We can pass this information into the constructor of the form without any trouble as seen below. By passing in the DataSet we can add new records, delete records or whatever we need to do. The other benefit is since the dataset is passed by reference, any changes to it will automatically appear in the row the user just double clicked on. In order for the form fields to be auto bound to the record the user clicked on we need to set the DataBinding of the controls in the form to a BindingSource. The BindingSource serves as the go between between the UI and data store. Here’s a sample “CellDoubleClick” event that would happen in the DataGridView:
1 int id = Convert.ToInt32(DataGridView.Rows[e.RowIndex].Cells[0].Value);
2 MyForm myForm = new MyForm(dataSet, id);
3 myForm.Show();
As the form loads the problem we face is having to tell the BindingSource in the form which record we want to set as the BindingSource.Current item. At first glance it looks like we would just get the DataRow and then set it as the Current property. Wrong. The BindingSource.Current property has only a get accessor. Instead we need to use the BindingSource.Position property. Note: Any change to the position property updates the current property used by the bindingsource. The problem we face now is the BindingSource.Position property wants to know the index of the item in the underlying DataSource.
We don’t know the index value used by the BindingSource but we do know the ID we want to use. This is where the BindingSource.Find() method comes in. Using the find method we can basically search the underlying datasource and retrieve the index of a given item. Here’s an example:
contactBindingSource.Position = contactBindingSource.Find(“Id”, 2);
Once the line above runs, it is going to search the column “Id” in the DataSource associated with the BindingSource and return the index of that item.
What if you use the same form to create a new item? Simple, call the BindingSource.AddNew() method which will add a new item to the underlying DataSource. Then move the index to the last item. Here’s a sample:
bindingSource.AddNew();
bindingSource.MoveLast();
Since items are always added at the end of the associated data source the MoveLast() method will set the index to the last item in the underlying datasource.
I hope this makes sense because it is an easy way to have a form bound to a DataSet and use the same form to perform “CRUD” operations with.