您好,登錄后才能下訂單哦!
這篇文章主要講解了“WPF如何實現(xiàn)帶篩選功能的DataGrid”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“WPF如何實現(xiàn)帶篩選功能的DataGrid”吧!
在本示例中,從數(shù)據(jù)綁定,到數(shù)據(jù)展示,涉及知識點如下所示:
DataGrid,要WPF提供的進(jìn)行二維數(shù)據(jù)展示在列表控件,默認(rèn)功能非常簡單,但是可以通過數(shù)據(jù)模板或者控件模板進(jìn)行擴展和美化,可伸縮性很強。
MVVM,是Model-View-ViewModel的簡寫,主要進(jìn)行數(shù)據(jù)和UI進(jìn)行前后端分離,在本示例中,主要用到的MVVM第三方庫為CommunityToolkit.Mvvm,大大簡化原生MVVM的實現(xiàn)方式。
集合視圖, 要對 DataGrid 中的數(shù)據(jù)進(jìn)行分組、排序和篩選,可以將其綁定到支持這些函數(shù)的 CollectionView。 然后,可以在不影響基礎(chǔ)源數(shù)據(jù)的情況下處理 CollectionView 中的數(shù)據(jù)。 集合視圖中的更改反映在 DataGrid 用戶界面 (UI) 中。
Popup控件,直接繼承FrameworkElement,提供了一種在單獨的窗口中顯示內(nèi)容的方法,該窗口相對于指定的元素或屏幕坐標(biāo),浮動在當(dāng)前Popup應(yīng)用程序窗口上,可用于懸浮窗口。
本示例主要模仿Excel的篩選功能進(jìn)行實現(xiàn),右鍵標(biāo)題欄打開浮動窗口,懸浮于標(biāo)題欄下方,既可以通過文本框進(jìn)行篩選,也可以通過篩選按鈕彈出右鍵菜單,選擇具體篩選方式,截圖如下所示:
選擇篩選方式,彈出窗口,如下所示:
輸入篩選條件,點擊確定,或者取消篩選。如篩選學(xué)號里面包含2的,效果如下所示:
注意:以上篩選都是客戶端篩選,不會修改數(shù)據(jù)源,也不會重連數(shù)據(jù)庫。
在本示例中,核心源碼主要包含以下幾個部分:
前端視圖【MainWindow.xaml】源碼
主要實現(xiàn)了按學(xué)號,姓名,年齡三列進(jìn)行篩選,既可以單列篩選,又可以組合篩選。且三列的篩選實現(xiàn)方式一致,僅是綁定列有差異。
<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="結(jié)尾" 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="學(xué)號" 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="學(xué)號" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combNoMenu1" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtNoMenu1" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"> <RadioButton x:Name="rbNoAnd" Content="與" IsChecked="True" Margin="4" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> <RadioButton x:Name="rbNoOr" Content="或" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"> <TextBlock Text="學(xué)號" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combNoMenu2" Height="28" Margin="4" Width="100" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtNoMenu2" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <Button Tag="No" Content="取消" Width="100" Height="28" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="0" Click="btnCancelFilter_Click"></Button> <Button Tag="No" Content="確定" Width="100" Height="28" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1" Click="btnOkFilter_Click"></Button> </Grid> </Border> </Popup> <Popup x:Name="popupNameMenu" Width="300" MaxHeight="500" Height="200" PopupAnimation="Slide" AllowsTransparency="False" Tag=""> <Border BorderThickness="1" BorderBrush="Beige" Padding="15" Background="AliceBlue"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0"> <TextBlock Text="姓名" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combNameMenu1" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtNameMenu1" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0"> <RadioButton x:Name="rbNameAnd" Content="與" IsChecked="True" Margin="4" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> <RadioButton x:Name="rbNameOr" Content="或" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="0"> <TextBlock Text="姓名" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combNameMenu2" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtNameMenu2" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <Button Tag="Name" Content="取消" Width="100" Height="28" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="0" Click="btnCancelFilter_Click"></Button> <Button Tag="Name" Content="確定" Width="100" Height="28" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1" Click="btnOkFilter_Click"></Button> </Grid> </Border> </Popup> <Popup x:Name="popupAgeMenu" Width="300" MaxHeight="500" Height="200" PopupAnimation="Slide" AllowsTransparency="False" Tag=""> <Border BorderThickness="1" BorderBrush="Beige" Padding="15" Background="AliceBlue"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0"> <TextBlock Text="年齡" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combAgeMenu1" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtAgeMenu1" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0"> <RadioButton x:Name="rbAgeAnd" Content="與" IsChecked="True" Margin="4" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> <RadioButton x:Name="rbAgeOr" Content="或" Background="AliceBlue" VerticalAlignment="Center" VerticalContentAlignment="Center"></RadioButton> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="0"> <TextBlock Text="年齡" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="combAgeMenu2" Height="28" Width="100" Margin="4" VerticalContentAlignment="Center"> <ComboBoxItem Content="等于" ></ComboBoxItem> <ComboBoxItem Content="不等于"></ComboBoxItem> <ComboBoxItem Content="開頭"></ComboBoxItem> <ComboBoxItem Content="結(jié)尾"></ComboBoxItem> <ComboBoxItem Content="包含"></ComboBoxItem> <ComboBoxItem Content="不包含"></ComboBoxItem> </ComboBox> <TextBox x:Name="txtAgeMenu2" Height="28" Width="100" VerticalContentAlignment="Center"></TextBox> </StackPanel> <Button Tag="Age" Content="取消" Width="100" Height="28" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="0" Click="btnCancelFilter_Click"></Button> <Button Tag="Age" Content="確定" Width="100" Height="28" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1" Click="btnOkFilter_Click"></Button> </Grid> </Border> </Popup> </Grid> </Window>
業(yè)務(wù)邏輯【MainWindowViewModel】
業(yè)務(wù)邏輯處理主要復(fù)責(zé)數(shù)據(jù)初始化等業(yè)務(wù)相關(guān)內(nèi)容,和UI無關(guān),如下所示:
using CommunityToolkit.Mvvm.ComponentModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DemoDataGrid { public class MainWindowViewModel:ObservableObject { #region 屬性及構(gòu)造函數(shù) private List<Student> students; public List<Student> Students { get { return students; } set { SetProperty(ref students, value); } } private List<FilterInfo> names; public List<FilterInfo> Names { get { return names; } set { SetProperty(ref names, value); } } private List<FilterInfo> nos; public List<FilterInfo> Nos { get { return nos; } set {SetProperty(ref nos , value); } } private List<FilterInfo> ages; public List<FilterInfo> Ages { get { return ages; } set {SetProperty(ref ages , value); } } public MainWindowViewModel() { this.Students= new List<Student>(); for (int i = 0; i < 20; i++) { this.Students.Add(new Student() { Id = i, Name = $"張{i}牛", Age = (i % 10) + 10, No = i.ToString().PadLeft(4, '0'), }); } this.Nos= new List<FilterInfo>(); this.Names= new List<FilterInfo>(); this.Ages= new List<FilterInfo>(); this.Students.ForEach(s => { this.Nos.Add(new FilterInfo() { FilterText=s.No,IsChecked=false }); this.Names.Add(new FilterInfo() { FilterText = s.Name, IsChecked = false }); this.Ages.Add(new FilterInfo() { FilterText = s.Age.ToString(), IsChecked = false }); }); this.Ages=this.Ages.Distinct().ToList();//去重 } #endregion } }
篩選功能實現(xiàn)【MainWindow.xaml.cs】
本示例為了簡化實現(xiàn),篩選功能處理主要在cs后端實現(xiàn),如下所示:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DemoDataGrid { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private MainWindowViewModel viewModel; public MainWindow() { InitializeComponent(); viewModel = new MainWindowViewModel(); this.DataContext = viewModel; } #region 篩選 private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (sender != null && sender is TextBlock) { var textBlock = sender as TextBlock; var tag = textBlock.Tag.ToString(); var pop = this.FindName($"popup{tag}"); if (pop != null) { var popup = pop as System.Windows.Controls.Primitives.Popup; if (popup != null) { popup.IsOpen = true; popup.PlacementTarget = textBlock; popup.Placement = System.Windows.Controls.Primitives.PlacementMode.RelativePoint; popup.VerticalOffset = 10; popup.HorizontalOffset = 10; } } } } private void TextBox_TextChanged(object sender, TextChangedEventArgs e) { TextBox textBox = e.OriginalSource as TextBox; var tag = textBox.Tag;//條件 var text = textBox.Text; if (tag != null) { if (tag.ToString() == "No") { Filter(this.lbNos.ItemsSource, this.txtNo.Text); } if (tag.ToString() == "Name") { Filter(this.lbNames.ItemsSource, this.txtName.Text); } if (tag.ToString() == "Age") { Filter(this.lbAges.ItemsSource, this.txtAge.Text); } } } private void Filter(object source, string filter) { var cv = CollectionViewSource.GetDefaultView(source); if (cv != null && cv.CanFilter) { cv.Filter = new Predicate<object>((obj) => { bool flag = true; var t = obj as FilterInfo; if (t != null) { flag = t.FilterText.Contains(filter); } return flag; }); } } private void popup_MouseLeave(object sender, MouseEventArgs e) { var popup = e.OriginalSource as System.Windows.Controls.Primitives.Popup; var showContext = (this.FindResource("queryConditionMenu") as ContextMenu)?.IsOpen; if (popup != null && showContext==false) { popup.IsOpen = false; } } private void btnCancel_Click(object sender, RoutedEventArgs e) { var btn = e.OriginalSource as Button; if (btn != null) { var tag = btn.Tag; if (tag.ToString() == "No") { ClearFilter(this.txtNo, this.viewModel.Nos); } if (tag.ToString() == "Name") { ClearFilter(this.txtName, this.viewModel.Names); } if (tag.ToString() == "Age") { ClearFilter(this.txtAge, this.viewModel.Ages); } FilterTask();//清除以后,重新刷新 } } private void ClearFilter(TextBox textBox, List<FilterInfo> collection) { textBox.Clear(); foreach (var f in collection) { f.IsChecked = false; } } private void btnOk_Click(object sender, RoutedEventArgs e) { // FilterTask(); } private void FilterTask() { var cv = CollectionViewSource.GetDefaultView(this.dgStudents.ItemsSource); if (cv != null && cv.CanFilter) { cv.Filter = new Predicate<object>((obj) => { bool flag = true; var t = obj as Student; if (t != null) { var nos = this.viewModel.Nos.Where(r => r.IsChecked == true).ToList(); var names = this.viewModel.Names.Where(r => r.IsChecked == true).ToList(); var ages = this.viewModel.Ages.Where(r => r.IsChecked == true).ToList(); if (nos.Count() > 0) { flag = flag && nos.Select(r => r.FilterText).Contains(t.No); } if (names.Count() > 0) { flag = flag && names.Select(r => r.FilterText).Contains(t.Name); } if (ages.Count() > 0) { flag = flag && ages.Select(r => r.FilterText).Contains(t.Age.ToString()); } } return flag; }); } } #endregion private List<string> condition = new List<string>() { "Equal", "NotEqual", "Begin", "End", "In", "NotIn" }; private void ButtonFilter_Click(object sender, RoutedEventArgs e) { var btn = e.OriginalSource as Button; if (btn != null) { var tag = btn.Tag; var popup = this.FindName($"popup{tag}") as System.Windows.Controls.Primitives.Popup; if (popup != null) { popup.IsOpen = true; } if (btn.ContextMenu.IsOpen) { btn.ContextMenu.IsOpen = false; } else { btn.ContextMenu.Tag = tag; btn.ContextMenu.Width = 100; btn.ContextMenu.Height = 150; btn.ContextMenu.IsOpen = true; btn.ContextMenu.PlacementTarget = btn; btn.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom; } } } private void ContextMenu_MouseLeave(object sender, MouseEventArgs e) { var menu = e.OriginalSource as ContextMenu; if (menu != null) { menu.IsOpen = false; } } private void ContextMenu_Click(object sender, RoutedEventArgs e) { var contextMenu = sender as ContextMenu; if (contextMenu == null) { return; } var menuItem = e.OriginalSource as MenuItem; if (menuItem == null) { return; } var tag1 = contextMenu.Tag.ToString();//點擊的哪一個按鈕 var tag2 = menuItem.Tag.ToString();//點擊的是哪一個菜單 var pop = this.FindName($"popup{tag1}Menu"); var comb = this.FindName($"comb{tag1}Menu1"); HideParentPopup(tag1);//隱藏父Popup if (comb != null) { var combMenu = comb as ComboBox; combMenu.SelectedIndex = condition.IndexOf(tag2); } if (pop != null) { var popup = pop as System.Windows.Controls.Primitives.Popup; popup.IsOpen = true; popup.PlacementTarget = dgStudents; popup.Placement = System.Windows.Controls.Primitives.PlacementMode.Center; } } private void btnCancelFilter_Click(object sender, RoutedEventArgs e) { if (sender == null) { return; } var btn = sender as System.Windows.Controls.Button; if (btn != null) { var tag = btn.Tag.ToString(); HidePopupMenu(tag);//隱藏Popup控件 if (tag == "No") { ClearMenuFilter(this.txtNoMenu1, this.txtNoMenu2); } if (tag == "Name") { ClearMenuFilter(this.txtNameMenu1, this.txtNameMenu2); } if (tag == "Age") { ClearMenuFilter(this.txtAgeMenu1, this.txtAgeMenu2); } FilterMenuTask(); } } private void btnOkFilter_Click(object sender, RoutedEventArgs e) { if (sender == null) { return; } var btn = sender as System.Windows.Controls.Button; if (btn != null) { var tag = btn.Tag.ToString(); HidePopupMenu(tag); FilterMenuTask(); } } /// <summary> /// 隱藏父Popup /// </summary> /// <param name="tag"></param> private void HideParentPopup(string tag) { //點擊右鍵菜單時,隱藏父Popup控件 if (tag == "No") { this.popupNo.IsOpen = false; } if (tag == "Name") { this.popupName.IsOpen = false; } if (tag == "Age") { this.popupAge.IsOpen = false; } } /// <summary> /// 隱藏菜單彈出的Popup控件 /// </summary> /// <param name="tag"></param> private void HidePopupMenu(string tag) { var pop = this.FindName($"popup{tag}Menu"); if (pop != null) { var popup = pop as System.Windows.Controls.Primitives.Popup; popup.IsOpen = false; } } /// <summary> /// 清除菜單中的文本過濾條件 /// </summary> /// <param name="txt1"></param> /// <param name="txt2"></param> private void ClearMenuFilter(TextBox txt1, TextBox txt2) { txt1?.Clear(); txt2?.Clear(); } /// <summary> /// /// </summary> private void FilterMenuTask() { var cv = CollectionViewSource.GetDefaultView(this.dgStudents.ItemsSource); if (cv != null && cv.CanFilter) { cv.Filter = new Predicate<object>((obj) => { bool flag = true; var t = obj as Student; if (t != null) { string noText1 = this.txtNoMenu1.Text.Trim(); string noText2 = this.txtNoMenu2.Text.Trim(); int noConditionType1 = this.combNoMenu1.SelectedIndex; int noConditionType2 = this.combNoMenu2.SelectedIndex; string nameText1 = this.txtNameMenu1.Text.Trim(); string nameText2 = this.txtNameMenu2.Text.Trim(); int nameConditionType1 = this.combNameMenu1.SelectedIndex; int nameConditionType2 = this.combNameMenu2.SelectedIndex; string ageText1 = this.txtAgeMenu1.Text.Trim(); string ageText2 = this.txtAgeMenu2.Text.Trim(); int ageConditionType1 = this.combAgeMenu1.SelectedIndex; int ageConditionType2 = this.combAgeMenu2.SelectedIndex; bool? isNoAnd = this.rbNoAnd.IsChecked; bool? isNoOr = this.rbNoOr.IsChecked; bool? isNameAnd = this.rbNameAnd.IsChecked; bool? isNameOr = this.rbNameOr.IsChecked; bool? isAgeAnd = this.rbAgeAnd.IsChecked; bool? isAgeOr = this.rbAgeOr.IsChecked; bool flagNo = true; bool flagName = true; bool flagAge = true; flagNo = CheckConditions(noConditionType1, noConditionType2, t.No, noText1, noText2, isNoAnd, isNoOr); flagName = CheckConditions(nameConditionType1, nameConditionType2, t.Name, nameText1, nameText2, isNameAnd, isNameOr); flagAge = CheckConditions(ageConditionType1, ageConditionType2, t.Age.ToString(), ageText1, ageText2, isAgeAnd, isAgeOr); flag = flag && flagNo && flagName && flagAge; } return flag; }); } } private bool CheckConditions(int conditionIndex1, int conditionIndex2, string source, string condition1, string condition2, bool? isAnd, bool? isOr) { bool flag = true; bool flag1 = true; bool flag2 = true; if (!string.IsNullOrEmpty(condition1) && !string.IsNullOrWhiteSpace(condition1) && conditionIndex1 != -1) { flag1 = CheckCondition(conditionIndex1, source, condition1); } if (!string.IsNullOrEmpty(condition2) && !string.IsNullOrWhiteSpace(condition2) && conditionIndex2 != -1) { flag2 = CheckCondition(conditionIndex2, source, condition2); } if (isAnd == true) { flag = flag1 && flag2; } if (isOr == true) { flag = flag1 || flag2; } return flag; } private bool CheckCondition(int condtionIndex, string source, string condition) { bool flag = true; if (condtionIndex == 0) { flag = flag && source == condition; } if (condtionIndex == 1) { flag = flag && source != condition; } if (condtionIndex == 2) { flag = flag && source.StartsWith(condition); } if (condtionIndex == 3) { flag = flag && source.EndsWith(condition); } if (condtionIndex == 4) { flag = flag && source.Contains(condition); } if (condtionIndex == 5) { flag = flag && !source.Contains(condition); } return flag; } } }
學(xué)號,姓名,年齡三列過濾列表綁定內(nèi)容模型一致,為FilterInfo,如下所示:
using CommunityToolkit.Mvvm.ComponentModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DemoDataGrid { public class FilterInfo : ObservableObject { private string filterText; public string FilterText { get { return filterText; } set { SetProperty(ref filterText, value); } } private bool isChecked; public bool IsChecked { get { return isChecked; } set { SetProperty(ref isChecked, value); } } } }
感謝各位的閱讀,以上就是“WPF如何實現(xiàn)帶篩選功能的DataGrid”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對WPF如何實現(xiàn)帶篩選功能的DataGrid這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。