Roy Osherove

View Original

Data Binding Woes - A Simple Solution

Wooho! Found the solution to the Data Binding problem I was having. I got it from this free book chapter: How to use Data Views  from this book.

I'll explain the problem and then the solution.

Problem: How do you get the desired position in a BindingContext, when all you have to go on is a DataRow object?

This problem would occur whenever you wanted a control other that a DataGrid to serve as a 'master' in a master-details data bound form. Imagine that the control that you have is a treeview. You filled up the treeNodes and set the node.Tag property with a DataRow object . You want the user to be able to click on a tree node and let a DataGrid on the form show the child rows of the selected DataRow.

Now, If we have a ListBox or ComboBox control, this could be easy. You just set the BindingManager's Position property to the current index of the control. But what about a treeview? Where is the $#%! index there?

The solution is pretty darn simple: using a DataView object!

A DataView object has the ability to find a row based on a key and a value, meaning that if the DataRow is sorted according to the primary key of the table, you can use it too look up a row based on a given primary key. It contains a Find method which, how comfortable, return the index to the row that was found. so, all you have to do is create a new DataView object, make it sort on your PK, and use it to find and index. Then you set the Binding manager's postion according to the returned index. Yu will need to bind your controls to that particular DataView, so you'll get the correct position(no biggie). One word of caution - a DataTable object has by default a DefaultDataView property which you can use. It is recommended to use a new DataView object, which gives you more flexibilty, and hey, you can create 2 or even 10 different view of your data. You can sort them, you can filter them, hell, you can just show the rows that were last changed,added,deleted - you name it. It's all there using the DataView.

I just "got" it, and I like it!

Here's the code to handle the user selecting a tree node:


//Create a custom view of the data

private DataView view = new DataView(m_ds.Tables["Stuff"]);

//make it sort based on the PK

view.Sort="ID";

 

//Handling a listbox event

private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)

{

      //get the binding manager to set the position

      BindingManagerBase bind = BindingContext[m_ds,"Stuff"];

 

      //Using the 'Find' of the DataView

      //returns the needed row index!

      //Just make sure you bind the ValueMember

      //property of the listbox

      bind.Position= view.Find(listBox1.SelectedValue);

}

 

//Handling a TreeView event

private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)

{

      //get the binding manager to set the position

      BindingManagerBase bind = BindingContext[m_ds,"Stuff"];

 

      DataRow row = (DataRow)treeView1.SelectedItem.Tag;

      int wantedID = int.Parse(row["ID"].ToString());

      bind.Position= view.Find(wantedID);

}