Using a WPF ListView as a DataGrid
- by psheriff
Many people like to view data in a grid format of rows and columns. WPF did not come with a data grid control that automatically creates rows and columns for you based on the object you pass it. However, the WPF Toolkit can be downloaded from CodePlex.com that does contain a DataGrid control. This DataGrid gives you the ability to pass it a DataTable or a Collection class and it will automatically figure out the columns or properties and create all the columns for you and display the data.The DataGrid control also supports editing and many other features that you might not always need. This means that the DataGrid does take a little more time to render the data. If you want to just display data (see Figure 1) in a grid format, then a ListView works quite well for this task. Of course, you will need to create the columns for the ListView, but with just a little generic code, you can create the columns on the fly just like the WPF Toolkit’s DataGrid.
Figure 1: A List of Data using a ListView
A Simple ListView ControlThe XAML below is what you would use to create the ListView shown in Figure 1. However, the problem with using XAML is you have to pre-define the columns. You cannot re-use this ListView except for “Product” data.
<ListView x:Name="lstData" ItemsSource="{Binding}"> <ListView.View> <GridView> <GridViewColumn Header="Product ID" Width="Auto" DisplayMemberBinding="{Binding Path=ProductId}" /> <GridViewColumn Header="Product Name" Width="Auto" DisplayMemberBinding="{Binding Path=ProductName}" /> <GridViewColumn Header="Price" Width="Auto" DisplayMemberBinding="{Binding Path=Price}" /> </GridView> </ListView.View></ListView>
So, instead of creating the GridViewColumn’s in XAML, let’s learn to create them in code to create any amount of columns in a ListView.
Create GridViewColumn’s From Data TableTo display multiple columns in a ListView control you need to set its View property to a GridView collection object. You add GridViewColumn objects to the GridView collection and assign the GridView to the View property. Each GridViewColumn object needs to be bound to a column or property name of the object that the ListView will be bound to. An ADO.NET DataTable object contains a collection of columns, and these columns have a ColumnName property which you use to bind to the GridViewColumn objects.
Listing 1 shows a sample of reading and XML file into a DataSet object. After reading the data a GridView object is created. You can then loop through the DataTable columns collection and create a GridViewColumn object for each column in the DataTable. Notice the DisplayMemberBinding property is set to a new Binding to the ColumnName in the DataTable.
C#private void FirstSample(){ // Read the data DataSet ds = new DataSet(); ds.ReadXml(GetCurrentDirectory() + @"\Xml\Product.xml"); // Create the GridView GridView gv = new GridView();
// Create the GridView Columns foreach (DataColumn item in ds.Tables[0].Columns) { GridViewColumn gvc = new GridViewColumn(); gvc.DisplayMemberBinding = new Binding(item.ColumnName); gvc.Header = item.ColumnName; gvc.Width = Double.NaN; gv.Columns.Add(gvc); }
// Setup the GridView Columns lstData.View = gv; // Display the Data lstData.DataContext = ds.Tables[0];}
VB.NETPrivate Sub FirstSample() ' Read the data Dim ds As New DataSet() ds.ReadXml(GetCurrentDirectory() & "\Xml\Product.xml")
' Create the GridView Dim gv As New GridView()
' Create the GridView Columns For Each item As DataColumn In ds.Tables(0).Columns Dim gvc As New GridViewColumn() gvc.DisplayMemberBinding = New Binding(item.ColumnName) gvc.Header = item.ColumnName gvc.Width = [Double].NaN gv.Columns.Add(gvc) Next
' Setup the GridView Columns lstData.View = gv ' Display the Data lstData.DataContext = ds.Tables(0)End SubListing 1: Loop through the DataTable columns collection to create GridViewColumn objects
A Generic Method for Creating a GridViewInstead of having to write the code shown in Listing 1 for each ListView you wish to create, you can create a generic method that given any DataTable will return a GridView column collection. Listing 2 shows how you can simplify the code in Listing 1 by setting up a class called WPFListViewCommon and create a method called CreateGridViewColumns that returns your GridView.
C#private void DataTableSample(){ // Read the data DataSet ds = new DataSet(); ds.ReadXml(GetCurrentDirectory() + @"\Xml\Product.xml");
// Setup the GridView Columns lstData.View = WPFListViewCommon.CreateGridViewColumns(ds.Tables[0]); lstData.DataContext = ds.Tables[0];}
VB.NETPrivate Sub DataTableSample() ' Read the data Dim ds As New DataSet() ds.ReadXml(GetCurrentDirectory() & "\Xml\Product.xml")
' Setup the GridView Columns lstData.View = _ WPFListViewCommon.CreateGridViewColumns(ds.Tables(0)) lstData.DataContext = ds.Tables(0)End SubListing 2: Call a generic method to create GridViewColumns.
The CreateGridViewColumns MethodThe CreateGridViewColumns method will take a DataTable as a parameter and create a GridView object with a GridViewColumn object in its collection for each column in your DataTable.
C#public static GridView CreateGridViewColumns(DataTable dt){ // Create the GridView GridView gv = new GridView(); gv.AllowsColumnReorder = true;
// Create the GridView Columns foreach (DataColumn item in dt.Columns) { GridViewColumn gvc = new GridViewColumn(); gvc.DisplayMemberBinding = new Binding(item.ColumnName); gvc.Header = item.ColumnName; gvc.Width = Double.NaN; gv.Columns.Add(gvc); }
return gv;}
VB.NETPublic Shared Function CreateGridViewColumns _ (ByVal dt As DataTable) As GridView ' Create the GridView Dim gv As New GridView() gv.AllowsColumnReorder = True
' Create the GridView Columns For Each item As DataColumn In dt.Columns Dim gvc As New GridViewColumn() gvc.DisplayMemberBinding = New Binding(item.ColumnName) gvc.Header = item.ColumnName gvc.Width = [Double].NaN gv.Columns.Add(gvc) Next
Return gvEnd FunctionListing 3: The CreateGridViewColumns method takes a DataTable and creates GridViewColumn objects in a GridView.
By separating this method out into a class you can call this method anytime you want to create a ListView with a collection of columns from a DataTable.
SummaryIn this blog you learned how to create a ListView that acts like a DataGrid. You are able to use a DataTable as both the source of the data, and for creating the columns for the ListView. In the next blog entry you will learn how to use the same technique, but for Collection classes.
NOTE: You can download the complete sample code (in both VB and C#) at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "WPF ListView as a DataGrid" from the drop-down.
Good Luck with your Coding,Paul Sheriff
** SPECIAL OFFER FOR MY BLOG READERS **Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".