This problem would occur whenever you want a control other than a DataGrid to serve as a master in a master-details, data-bound form. Imagine that the control that you have is a tree view. You fill 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 data row.
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 tree view? The solution is pretty 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 to look up a row based on a given primary key. It contains a Find
method, which returns 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 an index. Then you set the Binding manager's position according to the returned index. You need to bind your controls to that particular DataView, so you get the correct position. One word of caution: a DataTable object has by default a DefaultDataView
property that you can use.
It is recommended to use a new DataView object, which gives you more flexibilty, and you can create 2 or even 10 different views of your data. You can sort them, filter them, or just show the rows that were last changed, added, deleted, or otherwise adapted. It's all there using the DataView.
Here's the code to handle the user selecting a tree node:
'Create a custom view of the data
Private view As New DataView(m_ds.Tables("Stuff"))
'make it sort based on the PK
view.Sort = "ID"
'Handling a listbox event
Private Sub listBox1_SelectedIndexChanged(sender As Object, e As System.EventArgs)
'get the binding manager to set the position
Dim bind As BindingManagerBase = 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)
End Sub 'listBox1_SelectedIndexChanged
'Handling a TreeView event
Private Sub treeView1_AfterSelect(sender As Object, e As System.Windows.Forms.TreeViewEventArgs)
'get the binding manager to set the position
Dim bind As BindingManagerBase = BindingContext(m_ds, "Stuff")
Dim row As DataRow = CType(treeView1.SelectedItem.Tag, DataRow)
Dim wantedID As Integer = Integer.Parse(row("ID").ToString())
bind.Position = view.Find(wantedID)
End Sub 'treeView1_AfterSelect
Comments