How do I Bind to a DataView instead of a DataTable

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a strongly typed dataset that I have been able to bind to a DataGrid
and other associated controls such that selecting a name in the DataGrid
displays the record in the associated controls using DataBinding and the
CurrencyManager. Add, Update and Delete are all working great.

Above the DataGrid I have 26 LinkLabels A-Z where (hopefully) the user will
be able to filter the names in the DataGrid.

I'm pretty sure I need to use a DataView in order to filter the records
based on the users Index (A-Z) selection but I am confused as to how to bind
everything to a DataView instead of the DataTable.

My Strongly Typed DataSet is goDS.

I use the following sample code to bind the controls:
txtFirstName.DataBindings.Add("Text", goDS, "tblGuests.FirstName")

To bind the DataGrid I use:
grd.SetDataBinding(goDS, "tblGuests")

To retrieve the CurrencyManager I use:
CType(BindingContext(goDS, "tblGuests"), CurrencyManager)

How can I bind everything to a DataView instead of a DataTable and still
have it all work in concert?

Any help would be most appreciated.
 
Jay,
When you bind to a DataTable, in reality you are binding to a DataView. Use
DataTable.DefaultView to get the DataView. Use
DataTable.DefaultView.RowFilter and DataTable.DefaultView.Sort to filter and
sort the DataView.

Regards,
Phil.
 
Based on the information below I have everything working except for one thing
- when I change the RowFilter on the DataView contained in the
DataViewManager with

goDVM.DataViewSettings(goDS.tblGuests).RowFilter = "LastName like 'A*'"

the grid does NOT reflect the filter. Calling the CurrencyManagers Refresh
method does not do the trick either.

If I set the RowFilter up before binding the grid it works but I need to
change it dynamically. Anybody know what I'm missing?

How to Bind to a DataView instead of a DataTable:
================================
You can use a DataViewManager to manage view settings for all the tables in
a DataSet. If you have a control that you want to bind to multiple tables,
such as a grid that navigates relationships, a DataViewManager is ideal.

To create the DateViewManager:

Dim moDVM As DataViewManager = New DataViewManager(goDS)

To bind the controls use:
txtFirstName.DataBindings.Add("Text", goDVM, "tblGuests.FirstName")

To bind the grid use:
grd.SetDataBinding(goDVM, "tblGuests")

To obtain the Currency Manager:
CType(BindingContext(goDVM, "tblGuests"), CurrencyManager)
 
Jay,
I've tried setting dataViewManager.DataViewSettings[ dataTable ].RowFilter
and get the same result as you.

Try goDS.tblGuests.DefaultView.RowFilter = "LastName like 'A*'" instead.
This should work if your dataGrid is bound to the default dataView.

If you are using creating your own dataViews, try (in C#)

DataView dataView = (DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
dataView.RowFilter = "LastName like 'A*'"

Regards,
Phil.
 
Phil

As you suggested Binding to the Tables Default View and manipulating it's
RowFilter property does indeed cause the grid to respond correctly.

I have read in a number of places that the correct way to bind is:
txtBox.DataBinding.Add("Text", MyDataSet, "MyTable.MyField")
grd.SetDataBinding(MyDataSet, "MyTable")
CType(BindingContext(MyDataSet, "MyTable"), CurrencyManager)

If you bind using the DataViewManager this syntax is preserved:
txtBox.DataBinding.Add("Text", MyDataViewManager, "MyTable.MyField")
grd.SetDataBinding(MyDataSet, "MyTable")
CType(BindingContext(MyDataSet, "MyTable"), CurrencyManager)

If you bind using the Tables Default View you end with:
txtBox.DataBinding.Add("Text", MyTable.DefaultView, "MyField")
grd.DataSource = MyTable.DefaultView
CType(BindingContext(goDS.tblTasks.DefaultView), CurrencyManager)

If I remember correctly the reason for binding the recommended way is
because the code generators do it that way and if you mix the two methods it
can cause problems.

Perhaps I will start a new thread on why the grid does not reflect the
DataView when binding with the DataViewManager.

Thanks for your help.


Phil Williams said:
Jay,
I've tried setting dataViewManager.DataViewSettings[ dataTable ].RowFilter
and get the same result as you.

Try goDS.tblGuests.DefaultView.RowFilter = "LastName like 'A*'" instead.
This should work if your dataGrid is bound to the default dataView.

If you are using creating your own dataViews, try (in C#)

DataView dataView = (DataView)((CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember ]).List;
dataView.RowFilter = "LastName like 'A*'"

Regards,
Phil.

Jay Pondy said:
Based on the information below I have everything working except for one thing
- when I change the RowFilter on the DataView contained in the
DataViewManager with

goDVM.DataViewSettings(goDS.tblGuests).RowFilter = "LastName like 'A*'"

the grid does NOT reflect the filter. Calling the CurrencyManagers Refresh
method does not do the trick either.

If I set the RowFilter up before binding the grid it works but I need to
change it dynamically. Anybody know what I'm missing?

How to Bind to a DataView instead of a DataTable:
================================
You can use a DataViewManager to manage view settings for all the tables in
a DataSet. If you have a control that you want to bind to multiple tables,
such as a grid that navigates relationships, a DataViewManager is ideal.

To create the DateViewManager:

Dim moDVM As DataViewManager = New DataViewManager(goDS)

To bind the controls use:
txtFirstName.DataBindings.Add("Text", goDVM, "tblGuests.FirstName")

To bind the grid use:
grd.SetDataBinding(goDVM, "tblGuests")

To obtain the Currency Manager:
CType(BindingContext(goDVM, "tblGuests"), CurrencyManager)
 
I have a related but different question. I'm trying to limit modofocation
access to a "tree" of datatables in a dataset, being shown in a datagrid. I
want a class of users of my app to be able to see but not add/edit/delete
data. I tried setting the .AllowNew/Edit/Delete properties to false on the
DefaultView of each of the datatables. This has no effect. Does anyone know
how to do this?
 
You can try to do this dynamically as you navigate to each child table in
the DataGrid.Navigate event.

private void dataGrid1_Navigate(object sender, NavigateEventArgs ne)
{
CurrencyManager cm = this.dataGrid1.BindingContext[dataGrid1.DataSource,
dataGrid1.DataMember] as CurrencyManager;
DataView dv = cm.List as DataView;
dv.AllowEdit = false;
Console.WriteLine(dv.Table.TableName);
}


==============
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools
 
Thanks Clay,
This does indeed work, with a little code to enforce the edit rules
*before* any navigation occurs. Clearly in your example I am modifying a
different DataView than the default DataView on each of the underlying tables
in my datasource. I find the CurrencyManager a little confusing and have
avoided it when possible, but it seems that in order to reasonably exploit
the functionality of WinForms in .NET, it can not be avoided :(

Thanks again,
Tyson

ClayB said:
You can try to do this dynamically as you navigate to each child table in
the DataGrid.Navigate event.

private void dataGrid1_Navigate(object sender, NavigateEventArgs ne)
{
CurrencyManager cm = this.dataGrid1.BindingContext[dataGrid1.DataSource,
dataGrid1.DataMember] as CurrencyManager;
DataView dv = cm.List as DataView;
dv.AllowEdit = false;
Console.WriteLine(dv.Table.TableName);
}


==============
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools

Tyson Kamp said:
I have a related but different question. I'm trying to limit modofocation
access to a "tree" of datatables in a dataset, being shown in a datagrid.
I
want a class of users of my app to be able to see but not add/edit/delete
data. I tried setting the .AllowNew/Edit/Delete properties to false on the
DefaultView of each of the datatables. This has no effect. Does anyone
know
how to do this?
 
Back
Top