这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WPF如何实现带筛选功能的DataGrid”吧!
涉及知识点
在本示例中,从数据绑定,到数据展示,涉及知识点如下所示:
DataGrid,要WPF提供的进行二维数据展示在列表控件,默认功能非常简单,但是可以通过数据模板或者控件模板进行扩展和美化,可伸缩性很强。
MVVM,是Model-View-ViewModel的简写,主要进行数据和UI进行前后端分离,在本示例中,主要用到的MVVM第三方库为CommunityToolkit.Mvvm,大大简化原生MVVM的实现方式。
集合视图, 要对 DataGrid 中的数据进行分组、排序和筛选,可以将其绑定到支持这些函数的 CollectionView。 然后,可以在不影响基础源数据的情况下处理 CollectionView 中的数据。 集合视图中的更改反映在 DataGrid 用户界面 (UI) 中。
Popup控件,直接继承FrameworkElement,提供了一种在单独的窗口中显示内容的方法,该窗口相对于指定的元素或屏幕坐标,浮动在当前Popup应用程序窗口上,可用于悬浮窗口。
示例截图
本示例主要模仿Excel的筛选功能进行实现,右键标题栏打开浮动窗口,悬浮于标题栏下方,既可以通过文本框进行筛选,也可以通过筛选按钮弹出右键菜单,选择具体筛选方式,截图如下所示:
选择筛选方式,弹出窗口,如下所示:
输入筛选条件,点击确定,或者取消筛选。如筛选学号里面包含2的,效果如下所示:
注意:以上筛选都是客户端筛选,不会修改数据源,也不会重连数据库。
核心源码
在本示例中,核心源码主要包含以下几个部分:
前端视图【MainWindow.xaml】源码
主要实现了按学号,姓名,年龄三列进行筛选,既可以单列筛选,又可以组合筛选。且三列的筛选实现方式一致,仅是绑定列有差异。
<Window x:Class="DemoDataGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DemoDataGrid"
mc:Ignorable="d"
Title="DataGrid筛选示例" Height="650" Width="800">
<Window.Resources>
<ResourceDictionary>
<CollectionViewSource x:Key="ItemsSource" Source="{Binding Path=Students}"></CollectionViewSource>
<CollectionViewSource x:Key="Names" Source="{Binding Path=Names}"></CollectionViewSource>
<CollectionViewSource x:Key="Nos" Source="{Binding Path=Nos}"></CollectionViewSource>
<CollectionViewSource x:Key="Ages" Source="{Binding Path=Ages}"></CollectionViewSource>
<Style x:Key="ListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="ScrollViewer.CanContentScroll" Value="True"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer x:Name="ScrollViewer" CanContentScroll="True">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Geometry x:Key="Icon_Filter">
M608 864C588.8 864 576 851.2 576 832L576 448c0-6.4 6.4-19.2 12.8-25.6L787.2 256c6.4-6.4 6.4-19.2 0-19.2 0-6.4-6.4-12.8-19.2-12.8L256 224c-12.8 0-19.2 6.4-19.2 12.8 0 6.4-6.4 12.8 6.4 19.2l198.4 166.4C441.6 428.8 448 441.6 448 448l0 256c0 19.2-12.8 32-32 32S384 723.2 384 704L384 460.8 198.4 307.2c-25.6-25.6-32-64-19.2-96C185.6 179.2 217.6 160 256 160L768 160c32 0 64 19.2 76.8 51.2 12.8 32 6.4 70.4-19.2 89.6l-192 160L633.6 832C640 851.2 627.2 864 608 864z
</Geometry>
<ContextMenu x:Key="queryConditionMenu" MouseLeave="ContextMenu_MouseLeave" MenuItem.Click="ContextMenu_Click">
<MenuItem FontSize="12" Header="等于" Tag="Equal"></MenuItem>
<MenuItem FontSize="12" Header="不等于" Tag="NotEqual"></MenuItem>
<MenuItem FontSize="12" Header="开头" Tag="Begin"></MenuItem>
<MenuItem FontSize="12" Header="结尾" Tag="End"></MenuItem>
<MenuItem FontSize="12" Header="包含" Tag="In"></MenuItem>
<MenuItem FontSize="12" Header="不包含" Tag="NotIn"></MenuItem>
</ContextMenu>
</ResourceDictionary>
</Window.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<DataGrid Grid.Row="1" x:Name="dgStudents" ItemsSource="{Binding Source={StaticResource ItemsSource} }" AutoGenerateColumns="False"
CanUserReorderColumns="True" CanUserDeleteRows="False" CanUserAddRows="False" HeadersVisibility="Column"
CanUserSortColumns="True"
VirtualizingPanel.VirtualizationMode="Recycling"
EnableColumnVirtualization="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True" GridLinesVisibility="All" RowHeight="25"
SelectionUnit="FullRow" SelectionMode="Single" IsReadOnly="True" FontSize="12"
SelectedIndex="{Binding SelectTaskItemIndex}" SelectedItem="{Binding SelectTaskItem}"
CanUserResizeColumns="True">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Id}" Header="Id" Width="*">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding No}" Width="*">
<DataGridTextColumn.Header>
<TextBlock Text="学号" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="No"></TextBlock>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Name}" Width="*">
<DataGridTextColumn.Header>
<TextBlock Text="姓名" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="Name"></TextBlock>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Age}" Width="*">
<DataGridTextColumn.Header>
<TextBlock Text="年龄" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="Age"></TextBlock>
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<Popup x:Name="popupNo" Width="135" MaxHeight="500" Height="Auto" PopupAnimation="Slide" AllowsTransparency="False" MouseLeave="popup_MouseLeave">
<Border BorderBrush="LightBlue" BorderThickness="1" Padding="5" Background="AliceBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBox Height="25" x:Name="txtNo" MinWidth="60" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Tag="No" TextChanged="TextBox_TextChanged"></TextBox>
<Button x:Name="btnNoFilter" Tag="No" ClickMode="Press" Click="ButtonFilter_Click" ContextMenu="{StaticResource queryConditionMenu}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Path Data="{StaticResource Icon_Filter}" Stroke="Gray" StrokeThickness="1"
Height="12" Width="12" Stretch="Fill"></Path>
<TextBlock Margin="2,0" Text="筛选" FontSize="12"></TextBlock>
</StackPanel>
</Button>
</StackPanel>
<ListBox x:Name="lbNos" ItemsSource="{Binding Source={StaticResource Nos}}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.IsVirtualizing="True" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding FilterText}" IsChecked="{Binding IsChecked}"></CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Tag="No" Content="取消" Width="60" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="0" Click="btnCancel_Click"></Button>
<Button Content="确定" Width="60" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1" Click="btnOk_Click"></Button>
</Grid>
</Border>
</Popup>
<Popup x:Name="popupName" Width="135" MaxHeight="500" Height="Auto" PopupAnimation="Slide" AllowsTransparency="False" MouseLeave="popup_MouseLeave">
<Border BorderBrush="LightBlue" BorderThickness="1" Padding="5" Background="AliceBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBox Height="25" x:Name="txtName" MinWidth="60" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Tag="Name" TextChanged="TextBox_TextChanged"></TextBox>
<Button x:Name="btnNameFilter" Tag="Name" Click="ButtonFilter_Click" ContextMenu="{StaticResource queryConditionMenu}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Path Data="{StaticResource Icon_Filter}" Stroke="Gray" StrokeThickness="1"
Height="12" Width="12" Stretch="Fill"></Path>
<TextBlock Margin="2,0" Text="筛选" FontSize="12"></TextBlock>
</StackPanel>
</Button>
</StackPanel>
<ListBox x:Name="lbNames" ItemsSource="{Binding Source={StaticResource Names}}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.IsVirtualizing="True" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding FilterText}" IsChecked="{Binding IsChecked}"></CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Tag="No" Content="取消" Width="60" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="0" Click="btnCancel_Click"></Button>
<Button Content="确定" Width="60" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1" Click="btnOk_Click"></Button>
</Grid>
</Border>
</Popup>
<Popup x:Name="popupAge" Width="135" MaxHeight="500" Height="Auto" PopupAnimation="Slide" AllowsTransparency="False" MouseLeave="popup_MouseLeave">
<Border BorderBrush="LightBlue" BorderThickness="1" Padding="5" Background="AliceBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBox Height="25" x:Name="txtAge" MinWidth="60" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Tag="Age" TextChanged="TextBox_TextChanged"></TextBox>
<Button x:Name="btnAgeFilter" Tag="Age" Click="ButtonFilter_Click" ContextMenu="{StaticResource queryConditionMenu}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Path Data="{StaticResource Icon_Filter}" Stroke="Gray" StrokeThickness="1"
Height="12" Width="12" Stretch="Fill"></Path>
<TextBlock Margin="2,0" Text="筛选" FontSize="12"></TextBlock>
</StackPanel>
</Button>
</StackPanel>
<ListBox x:Name="lbAges" ItemsSource="{Binding Source={StaticResource Ages}}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.IsVirtualizing="True" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding FilterText}" IsChecked="{Binding IsChecked}"></CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Tag="No" Content="取消" Width="60" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="0" Click="btnCancel_Click"></Button>
<Button Content="确定" Width="60" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1" Click="btnOk_Click"></Button>
</Grid>
</Border>
</Popup>
<Popup x:Name="popupNoMenu" Width="300" MaxHeight="500" Height="200" PopupAnimation="Slide" AllowsTransparency="False" Tag="">
<Border BorderThickness="1" BorderBrush="Beige" Padding="15" Background="AliceBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<TextBlock Text="学号" VerticalAlignment="Center"></TextBlock>
<ComboBox x:Name="combNoMenu1" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center">
<ComboBoxItem Content="等于" ></ComboBoxItem>
<ComboBoxItem Content="不等于"></ComboBoxItem>
<ComboBoxItem Content="开头"></ComboBoxItem>
&