Page 5 of 7
Binding to a Grid - WPF
There are a number of data grids available for WPF but the latest and the one most likely to become the standard WPF data grid is the one introduced with Visual Studio 2010. For an indepth look at how the DataGrid works see: Using the WPF DataGrid
This also introduces new ways of generating controls bound to data sources. Unfortunately in the case of the Windows Search data connector the automatic code generation doesn't work 100% because of the use of field names that contain dots - e.g. System.Filename. This might well be fixed in the future but for the moment we need to add some hand-generated code to make it work. This might prove useful in other situations.
If you have been following the project using a WPF application then so far everything has worked the same as in the case of a Windows Forms application. It is assumed that you have the data source called SearchResults already set up complete with a table called Table consisting of a single column called System.FileName.
There is one important change to be made to the data source before making use of it in data binding. Change the column's property Null Value from "Throw Exception" to Null. This allows empty rows in the database to exist without causing the application to crash.
To place a data bound control onto the form you have to move to the form designer and have the Data Sources window open next to it. From the drop-down list that appears next to the table you can select the control you want to bind to it. In this case make sure it's the DataGrid.
Select the DataGrid as the control to be bound to the Table.
To place a bound DataGrid on the form in principle all you have to do is drag it onto the design surface. This generates the XAML needed and some code to create the table adaptor and the view. The DataGrid is created with a column complete with suitable header and the XAML contains the static resources needed to create the database and the view.
Unfortunately the auto-generated code isn't particularly helpful. To make it all work we need to create a database and a view instance manually. The code in the button's click event handler is the same as for the Windows version plus some extra code to setup the data table and view bound to the grid.
First we setup the connection string, the connection object and the table adaptor as before:
string connectionString =
OleDbConnection SearchConnect =
OleDbDataAdapter SearchAdpt =
"SELECT Top 5 System.FileName
We can also setup the CollectionViewSource which is used to navigate through the data table and the database object using the static resources generated by the designer:
ColleCollectionViewSource ViewSource =
SearchResults SearchResults =
Finally we can fill the table with data:
At this point the DataGrid should fill with data but what actually happens is that fills with five blank lines. Whenever this happens it is a sign that the DataGrid is correctly bound to the database but the columns of the DataGrid are not bound to the fields in the table.
The reason in this case seems to be that the designer has generated an ADO data object with the column name _System_FileName but the view object has been generated with a column name System.Filename and the dot is interpreted by the binding engine as a hierarchical property i.e. the Filename property of the System object. There seems to be no easy way to correct this problem.
A solution using IEnumerable
One fairly easy to implement but advanced solution to the problem is to convert the data table in the database into an IEnumerable collection. We can even convert it into an IEnumerable collection of row objects and the good news is that each item in the collection has a property with the correct name, i.e. _System_FileName.
To convert to an IEnumerable collection we simply use the table's AsEnumberable method:
<SearchResults.TableRow> TableData =
Now TableData is a collection with the correct column names that we can bind to the DataGrid. This could be done by editing the XAML but it's just as easy to modify the values set in the generated XAML using code:
tableDataGrid.DataContext = TableData;
tableDataGrid.ItemsSource = TableData;
You also need to add:
Following these changes you should be able to see the first five rows of data listed in the DataGrid.
The WPF DataGrid in action
If you add aditional columns to the query you can repeat the drag-and-drop of the table to the designer and the DataGrid code will be regenerated to include the additional columns. You will, however, have to re-bind the new columns to the correct column names following the pattern of the first column.