在預設情況下,WPF提供的DataGrid僅擁有數據展示等簡單功能,如果要實現像Excel一樣複雜的篩選過濾功能,則相對比較麻煩。本文以一個簡單的小例子,簡述如何通過WPF實話DataGrid的篩選功能,僅供學習分享使用,如有不足之處,還請指正。 ...
在預設情況下,WPF提供的DataGrid僅擁有數據展示等簡單功能,如果要實現像Excel一樣複雜的篩選過濾功能,則相對比較麻煩。本文以一個簡單的小例子,簡述如何通過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】源碼
主要實現了按學號,姓名,年齡三列進行篩選,既可以單列篩選,又可以組合篩選。且三列的篩選實現方式一致,僅是綁定列有差異。
1 <Window x:Class="DemoDataGrid.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:DemoDataGrid" 7 mc:Ignorable="d" 8 Title="DataGrid篩選示例" Height="650" Width="800"> 9 <Window.Resources> 10 <ResourceDictionary> 11 <CollectionViewSource x:Key="ItemsSource" Source="{Binding Path=Students}"></CollectionViewSource> 12 <CollectionViewSource x:Key="Names" Source="{Binding Path=Names}"></CollectionViewSource> 13 <CollectionViewSource x:Key="Nos" Source="{Binding Path=Nos}"></CollectionViewSource> 14 <CollectionViewSource x:Key="Ages" Source="{Binding Path=Ages}"></CollectionViewSource> 15 <Style x:Key="ListBoxStyle" TargetType="{x:Type ListBox}"> 16 <Setter Property="ScrollViewer.CanContentScroll" Value="True"></Setter> 17 <Setter Property="Template"> 18 <Setter.Value> 19 <ControlTemplate TargetType="{x:Type ListBox}"> 20 <ScrollViewer x:Name="ScrollViewer" CanContentScroll="True"> 21 <ItemsPresenter></ItemsPresenter> 22 </ScrollViewer> 23 </ControlTemplate> 24 </Setter.Value> 25 </Setter> 26 </Style> 27 <Geometry x:Key="Icon_Filter"> 28 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 29 </Geometry> 30 <ContextMenu x:Key="queryConditionMenu" MouseLeave="ContextMenu_MouseLeave" MenuItem.Click="ContextMenu_Click"> 31 <MenuItem FontSize="12" Header="等於" Tag="Equal"></MenuItem> 32 <MenuItem FontSize="12" Header="不等於" Tag="NotEqual"></MenuItem> 33 <MenuItem FontSize="12" Header="開頭" Tag="Begin"></MenuItem> 34 <MenuItem FontSize="12" Header="結尾" Tag="End"></MenuItem> 35 <MenuItem FontSize="12" Header="包含" Tag="In"></MenuItem> 36 <MenuItem FontSize="12" Header="不包含" Tag="NotIn"></MenuItem> 37 </ContextMenu> 38 </ResourceDictionary> 39 40 </Window.Resources> 41 <Grid Margin="10"> 42 <Grid.RowDefinitions> 43 <RowDefinition Height="20"></RowDefinition> 44 <RowDefinition Height="*"></RowDefinition> 45 </Grid.RowDefinitions> 46 <DataGrid Grid.Row="1" x:Name="dgStudents" ItemsSource="{Binding Source={StaticResource ItemsSource} }" AutoGenerateColumns="False" 47 CanUserReorderColumns="True" CanUserDeleteRows="False" CanUserAddRows="False" HeadersVisibility="Column" 48 CanUserSortColumns="True" 49 VirtualizingPanel.VirtualizationMode="Recycling" 50 EnableColumnVirtualization="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True" GridLinesVisibility="All" RowHeight="25" 51 SelectionUnit="FullRow" SelectionMode="Single" IsReadOnly="True" FontSize="12" 52 SelectedIndex="{Binding SelectTaskItemIndex}" SelectedItem="{Binding SelectTaskItem}" 53 CanUserResizeColumns="True"> 54 <DataGrid.Columns> 55 <DataGridTextColumn Binding="{Binding Id}" Header="Id" Width="*"> 56 57 </DataGridTextColumn> 58 <DataGridTextColumn Binding="{Binding No}" Width="*"> 59 <DataGridTextColumn.Header> 60 <TextBlock Text="學號" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="No"></TextBlock> 61 </DataGridTextColumn.Header> 62 </DataGridTextColumn> 63 <DataGridTextColumn Binding="{Binding Name}" Width="*"> 64 <DataGridTextColumn.Header> 65 <TextBlock Text="姓名" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="Name"></TextBlock> 66 </DataGridTextColumn.Header> 67 </DataGridTextColumn> 68 <DataGridTextColumn Binding="{Binding Age}" Width="*"> 69 <DataGridTextColumn.Header> 70 <TextBlock Text="年齡" FontWeight="Regular" MouseRightButtonDown="TextBlock_MouseRightButtonDown" Tag="Age"></TextBlock> 71 </DataGridTextColumn.Header> 72 </DataGridTextColumn> 73 </DataGrid.Columns> 74 </DataGrid> 75 <Popup x:Name="popupNo" Width="135" MaxHeight="500" Height="Auto" PopupAnimation="Slide" AllowsTransparency="False" MouseLeave="popup_MouseLeave"> 76 <Border BorderBrush="LightBlue" BorderThickness="1" Padding="5" Background="AliceBlue"> 77 <Grid> 78 <Grid.ColumnDefinitions> 79 <ColumnDefinition></ColumnDefinition> 80 <ColumnDefinition></ColumnDefinition> 81 </Grid.ColumnDefinitions> 82 <Grid.RowDefinitions> 83 <RowDefinition></RowDefinition> 84 <RowDefinition></RowDefinition> 85 <RowDefinition></RowDefinition> 86 </Grid.RowDefinitions> 87 <StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal"> 88 <TextBox Height="25" x:Name="txtNo" MinWidth="60" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Tag="No" TextChanged="TextBox_TextChanged"></TextBox> 89 <Button x:Name="btnNoFilter" Tag="No" ClickMode="Press" Click="ButtonFilter_Click" ContextMenu="{StaticResource queryConditionMenu}"> 90 <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> 91 <Path Data="{StaticResource Icon_Filter}" Stroke="Gray" StrokeThickness="1" 92 Height="12" Width="12" Stretch="Fill"></Path> 93 <TextBlock Margin="2,0" Text="篩選" FontSize="12"></TextBlock> 94 </StackPanel> 95 </Button> 96 </StackPanel> 97 <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}"> 98 <ListBox.ItemTemplate> 99 <DataTemplate> 100 <CheckBox Content="{Binding FilterText}" IsChecked="{Binding IsChecked}"></CheckBox> 101 </DataTemplate> 102 </ListBox.ItemTemplate> 103 </ListBox> 104 105 <Button Tag="No" Content="取消" Width="60" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="0" Click="btnCancel_Click"></Button> 106 <Button Content="確定" Width="60" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1" Click="btnOk_Click"></Button> 107 </Grid> 108 </Border> 109 </Popup> 110 <Popup x:Name="popupName" Width="135" MaxHeight="500" Height="Auto" PopupAnimation="Slide" AllowsTransparency="False" MouseLeave="popup_MouseLeave"> 111 <Border BorderBrush="LightBlue" BorderThickness="1" Padding="5" Background="AliceBlue"> 112 <Grid> 113 <Grid.ColumnDefinitions> 114 <ColumnDefinition></ColumnDefinition> 115 <ColumnDefinition></ColumnDefinition> 116 </Grid.ColumnDefinitions> 117 <Grid.RowDefinitions> 118 <RowDefinition></RowDefinition> 119 <RowDefinition></RowDefinition> 120 <RowDefinition></RowDefinition> 121 </Grid.RowDefinitions> 122 <StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal"> 123 <TextBox Height="25" x:Name="txtName" MinWidth="60" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Tag="Name" TextChanged="TextBox_TextChanged"></TextBox> 124 <Button x:Name="btnNameFilter" Tag="Name" Click="ButtonFilter_Click" ContextMenu="{StaticResource queryConditionMenu}"> 125 <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> 126 <Path Data="{StaticResource Icon_Filter}" Stroke="Gray" StrokeThickness="1" 127 Height="12" Width="12" Stretch="Fill"></Path> 128 <TextBlock Margin="2,0" Text="篩選" FontSize="12"></TextBlock> 129 </StackPanel> 130 </Button> 131 </StackPanel> 132 <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}"> 133 <ListBox.ItemTemplate> 134 <DataTemplate> 135 <CheckBox Content="{Binding FilterText}" IsChecked="{Binding IsChecked}"></CheckBox> 136 </DataTemplate> 137 </ListBox.ItemTemplate> 138 </ListBox> 139 140 <Button Tag="No" Content="取消" Width="60" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="0" Click="btnCancel_Click"></Button> 141 <Button Content="確定" Width="60" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1" Click="btnOk_Click"></Button> 142 </Grid> 143 </Border> 144