Wondering how to filter a bound WPF DataGrid or ListView/GridView by via a ComboBox?
It’s easy enough to bind data from a database table into either a DataGrid or GridView. It’s actually easy to filter a grid of data by a combobox based on a lookup table as well — it’s just hard to find examples!
What follows is a tutorial on how to filter via a combobox a table bound to a DataGrid or GridView inside a ListView.
Requirements
- Visual Studio 2010 C# Express
- Northwind sample database, Compact Edition 3.5
- Two data tables connected via a relation, such as the Northwind Categories table’s relation to the Products table
Setup
- Create a new WPF application in Visual Studio 2010 C# Express
- Add an “Existing Item” to the project, changing the browse window filter to data
- Browse to “C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Samples” or wherever the Northwind database can be found on your system
- Select the ‘DataSet’ database model and all tables
Creating ComboBox and Grid
- Open the Toolbox window and drag a combobox onto the XAML Designer
- Open the Data Sources window and drag the Categories node to the XAML Designer and drop it into the ComboBox
- Open the Products node under the Categories node in the Data Sources window and set all its children to “None” instead of a control, except for Product ID, Supplier ID, Category ID, Product Name, and Unit Price
- Drag the Products node (make sure it’s set to a DataGrid or a List, depending on what grid you want) under the Categories node in the Data Sources window and drop it onto the XAML Designer under the ComboBox
- Optionally, add elements to the XAML Designer, like a label for the ComboBox
- Optionally, style the grid
ComboBox and DataGrid XAML
<Window x:Class="WPF_XAML_Grid_Filtering.ComboboxFilterDatagrid" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ComboboxFilterDatagrid" Height="300" Width="534" xmlns:my="clr-namespace:WPF_XAML_Grid_Filtering" Loaded="Window_Loaded"> <Window.Resources> <my:NorthwindDataSet x:Key="northwindDataSet" /> <CollectionViewSource x:Key="categoriesViewSource" Source="{Binding Path=Categories, Source={StaticResource northwindDataSet}}" /> <CollectionViewSource x:Key="categoriesProductsViewSource" Source="{Binding Path=Products_FK01, Source={StaticResource categoriesViewSource}}" /> </Window.Resources> <Grid DataContext="{StaticResource categoriesViewSource}"> <Label Content="Category:" Height="28" HorizontalAlignment="Left" Name="CategoryLabel" VerticalAlignment="Top" Width="77" Margin="0,12,0,0" /> <ComboBox Height="23" HorizontalAlignment="Left" Margin="83,12,0,0" Name="comboBoxFilterGrid" VerticalAlignment="Top" Width="219" DisplayMemberPath="Category Name" ItemsSource="{Binding}" SelectedValuePath="Category ID" /> <DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding Source={StaticResource categoriesProductsViewSource}}" Name="productsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="0,59,0,0"> <DataGrid.Columns> <DataGridTextColumn x:Name="product_IDColumn" Binding="{Binding Path=Product ID}" Header="Product ID" IsReadOnly="True" Width="Auto" /> <DataGridTextColumn x:Name="supplier_IDColumn" Binding="{Binding Path=Supplier ID}" Header="Supplier ID" Width="Auto" /> <DataGridTextColumn x:Name="category_IDColumn" Binding="{Binding Path=Category ID}" Header="Category ID" Width="Auto" /> <DataGridTextColumn x:Name="product_NameColumn" Binding="{Binding Path=Product Name}" Header="Product Name" Width="Auto" /> <DataGridTextColumn x:Name="unit_PriceColumn" Binding="{Binding Path=Unit Price}" Header="Unit Price" Width="Auto" /> </DataGrid.Columns> </DataGrid> </Grid> </Window>
No C# source needed.
ComboBox and ListBox GridView XAML
<Window x:Class="WPF_XAML_Grid_Filtering.ComboboxFilterListgrid" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ComboboxFilterListgrid" Height="300" Width="532" xmlns:my="clr-namespace:WPF_XAML_Grid_Filtering" Loaded="Window_Loaded"> <Window.Resources> <my:NorthwindDataSet x:Key="northwindDataSet" /> <CollectionViewSource x:Key="categoriesViewSource" Source="{Binding Path=Categories, Source={StaticResource northwindDataSet}}" /> <CollectionViewSource x:Key="categoriesProductsViewSource" Source="{Binding Path=Products_FK01, Source={StaticResource categoriesViewSource}}" /> </Window.Resources> <Grid DataContext="{StaticResource categoriesViewSource}"> <Label Content="Category:" Height="28" HorizontalAlignment="Left" Name="CategoryLabel" VerticalAlignment="Top" Width="77" /> <ComboBox Height="23" HorizontalAlignment="Left" Margin="91,0,0,0" Name="comboBox1" VerticalAlignment="Top" Width="182" DisplayMemberPath="Category Name" ItemsSource="{Binding}" SelectedValuePath="Category ID" /> <ListView ItemsSource="{Binding Source={StaticResource categoriesProductsViewSource}}" Margin="0,34,0,0" Name="productsListView" SelectionMode="Single"> <ListView.ItemContainerStyle> <Style> <Setter Property="Control.HorizontalContentAlignment" Value="Stretch" /> <Setter Property="Control.VerticalContentAlignment" Value="Stretch" /> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView> <GridViewColumn x:Name="product_IDColumn" Header="Product ID" Width="80"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Margin="6,-1,-6,-1" Text="{Binding Path=Product ID, Mode=OneWay}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn x:Name="supplier_IDColumn" Header="Supplier ID" Width="80"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Margin="-6,-1" Text="{Binding Path=Supplier ID, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn x:Name="category_IDColumn" Header="Category ID" Width="80"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Margin="-6,-1" Text="{Binding Path=Category ID, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn x:Name="product_NameColumn" Header="Product Name" Width="80"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Margin="-6,-1" Text="{Binding Path=Product Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn x:Name="unit_PriceColumn" Header="Unit Price" Width="80"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Margin="-6,-1" Text="{Binding Path=Unit Price, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView> </Grid> </Window>




Hi, I’m not sure if I got the good Northwind database(couldn’t find the Compact Edition)
If I follow your steps I’ll get only 2 elements in Window.Resources:
No DataSet. Do I need that ?
The rest of my xaml code looks the same.
Data is displayed in my combobox and my datagrid, but there’s no relation between them.
And another thing :
if my xaml file is a System.Windows.Controls.Page the behind-code is not auto-generated, only in a System.Windows.Window
–
Mihai
Mihai,
You’ll need datasets for this approach.
Double-check what you did under my Setup instructions, especially step #4, where you select the ‘DataSet’ database model and all tables when adding the Northwind database.
That will automatically setup the Northwind tables and appropriate relations, so when you drag and drop later in the instructions the controls will be populated correctly.
Let me know if you have further problems.
Cindy
The example is designed to work windows, not page controls. I haven’t tackled page controls yet.
Cindy