WPF如何实现带筛选功能的DataGrid

作者:有用网 阅读量:221 发布时间:2024-01-07
关键字 wpf

这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WPF如何实现带筛选功能的DataGrid”吧!

涉及知识点

在本示例中,从数据绑定,到数据展示,涉及知识点如下所示:

  • DataGrid,要WPF提供的进行二维数据展示在列表控件,默认功能非常简单,但是可以通过数据模板或者控件模板进行扩展和美化,可伸缩性很强。

  • MVVM,是Model-View-ViewModel的简写,主要进行数据和UI进行前后端分离,在本示例中,主要用到的MVVM第三方库为CommunityToolkit.Mvvm,大大简化原生MVVM的实现方式。

  • 集合视图, 要对 DataGrid 中的数据进行分组、排序和筛选,可以将其绑定到支持这些函数的 CollectionView。 然后,可以在不影响基础源数据的情况下处理 CollectionView 中的数据。 集合视图中的更改反映在 DataGrid 用户界面 (UI) 中。

  • Popup控件,直接继承FrameworkElement,提供了一种在单独的窗口中显示内容的方法,该窗口相对于指定的元素或屏幕坐标,浮动在当前Popup应用程序窗口上,可用于悬浮窗口。

示例截图

本示例主要模仿Excel的筛选功能进行实现,右键标题栏打开浮动窗口,悬浮于标题栏下方,既可以通过文本框进行筛选,也可以通过筛选按钮弹出右键菜单,选择具体筛选方式,截图如下所示:

WPF如何实现带筛选功能的DataGrid

选择筛选方式,弹出窗口,如下所示:

WPF如何实现带筛选功能的DataGrid

输入筛选条件,点击确定,或者取消筛选。如筛选学号里面包含2的,效果如下所示:

WPF如何实现带筛选功能的DataGrid

 注意:以上筛选都是客户端筛选,不会修改数据源,也不会重连数据库。

核心源码

在本示例中,核心源码主要包含以下几个部分:

前端视图【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>
                 &

#发表评论
提交评论