• 在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果


    我在前面随笔《在Winform系统开发中,对表格列表中的内容进行分组展示》,介绍了Winform程序中对表格内容进行了分组的展示,在WPF应用中,同样也可以对表格的内容进行分组展示,不过处理方式和Winform有所差异,本篇随笔同样基于SqlSugar开发框架的基础上,实现在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果。

    1、回顾Winform的表格分组展示效果

    对于常规的二维表格数据,如下所示。

    我们根据其中一个字段对表格数据进行分组展示,这样更方便用户对特定数据的归类展示处理。

    Winform的界面中,我们基于DevExpress的GridView控件对数据进行分组展示,其中代码如下所示。

    复制代码
    //增加汇总字段和显示
    var gridView1 = this.winGridViewPager1.gridView1;
    if (checkGroup.Checked)
    {
        this.winGridViewPager1.ShowLineNumber = false;
        gridView1.IndicatorWidth = 0;
        gridView1.OptionsView.ShowGroupExpandCollapseButtons = true;//显示折叠的分组
        gridView1.OptionsView.AllowCellMerge = true; //允许合并字段
        gridView1.OptionsView.GroupDrawMode = GroupDrawMode.Standard;
    
        gridView1.GroupSummary.Clear();
        gridView1.Columns["Category"].GroupIndex = 0;//对类别进行分组展示
    
        var item = new GridGroupSummaryItem();
        item.FieldName = "Id";
        item.DisplayFormat = "  (合计数量 = {0:n})";
        item.SummaryType = DevExpress.Data.SummaryItemType.Count;//Sum、Average等
        gridView1.GroupSummary.Add(item);
        gridView1.ExpandAllGroups();
    }
    else
    {
        gridView1.GroupSummary.Clear();
        this.winGridViewPager1.ShowLineNumber = true;
        gridView1.OptionsView.AllowCellMerge = false;
    }
    复制代码

    我们可以看到,只需要实现对 GroupSummary的添加处理即可实现汇总效果的展示。

    2、在WPF应用中实现DataGrid的分组显示

    在WPF应用中,数据的显示通过DataGrid控件进行展示,默认是没有分组效果的,如果需要分组效果,需要定制表格的分组样式才能达到效果。

    我们同样基于SqlSugar开发框架的基础上,基于原料表的数据展示,实现在WPF应用中实现DataGrid的分组显示,实现的效果如下所示。

    我们这里根据【类别】字段来进行分组统一,其中分组样式在XAML上定义如下所示。

    复制代码
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="True">
                                    <Expander.Header>
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock FontWeight="Bold" Text="类别:" />
                                            <TextBlock FontWeight="Bold" Text="{Binding Name}" />
                                            <TextBlock Text="{Binding ItemCount, StringFormat='    (合计数量 = {0} )'}" />
                                        StackPanel>
                                    Expander.Header>
                                    <ItemsPresenter />
                                Expander>
                            ControlTemplate>
                        Setter.Value>
                    Setter>
                Style>
            GroupStyle.ContainerStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock FontWeight="Bold" Text="{Binding Name}" />
                DataTemplate>
            GroupStyle.HeaderTemplate>
        GroupStyle>
    DataGrid.GroupStyle>
    复制代码

    如果我们需要控件的虚拟化处理(提高显示性能),那么设置下虚拟化处理属性即可。

    复制代码
    <DataGrid
        x:Name="grid"
        Grid.Row="1"
        hc:DataGridAttach.ShowRowNumber="True"
        AutoGenerateColumns="False"
        HeadersVisibility="All"
        IsReadOnly="True"
        ItemsSource="{Binding ViewModel.Items}"
        MouseDoubleClick="DataGrid_MouseDoubleClick"
        RowHeaderWidth="60"
        SelectionChanged="DataGrid_SelectionChanged"
        SelectionMode="Extended"
        VerticalScrollBarVisibility="Auto"
        VirtualizingPanel.IsVirtualizing="True"
        VirtualizingPanel.IsVirtualizingWhenGrouping="True"
     >
    复制代码

    表格的字段,如没有特殊处理,我们用常用的定义效果即可,如下所示。

    复制代码
    <DataGrid.Columns>
        <DataGridTextColumn
            Width="SizeToCells"
            MinWidth="100"
            Binding="{Binding Id}"
            Header="ID编号" />
        <DataGridTextColumn
            Width="SizeToCells"
            MinWidth="100"
            Binding="{Binding Category}"
            Header="类别" />
        <DataGridTextColumn
            Width="SizeToCells"
            MinWidth="100"
            Binding="{Binding Code}"
            Header="原料编码" />
            ..............
    DataGrid.Columns>
    复制代码

    对于分组的效果处理,我们后台的C#代码也需要进行一定的适应处理,如下所示。

    我们采用MVVM的模式处理查询操作,获得数据并转换为CollectionView后,设置分组信息即可,如下代码所示。

    复制代码
    /// 
    /// 查询处理
    /// 
    [RelayCommand]
    private async Task Search()
    {
        //查询获得视图模型的数据
        await this.ViewModel.SearchCommand.ExecuteAsync(null);
    
        //把数据集合转换为CollectionView,并设置其GroupDescriptions
        var viewSource = CollectionViewSource.GetDefaultView(this.ViewModel.Items);
        if (this.ViewModel.IsUseGroup)
        {
            viewSource.GroupDescriptions.Clear();
            viewSource.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
        }
        this.grid.ItemsSource = viewSource;
    }
    复制代码

    这样就是写了数据的显示和分组处理了。

    上面的SearchCommand就是视图模型基类函数的查询获得数据的处理方式。

    复制代码
        /// 
        /// 触发查询处理命令
        /// 
        /// 
        [RelayCommand]
        public virtual async Task Search()
        {
            //切换第一页
            this.PagerInfo.CurrentPageIndex = 1;
            //查询更新
            await GetData();
        }
    复制代码

    GetData也是视图模型基类函数的通用处理方式,通过分页和条件信息,获得对应的数据记录。

    复制代码
        /// 
        /// 根据分页和查询条件查询,请求数据
        /// 
        /// 
        public virtual async Task GetData()
        {       
            //转换下分页信息
            ConvertPagingInfo();
            var result = await service.GetListAsync(this.PageDto);
            if (result != null)
            {
                this.Items = result.Items?.ToList();
                this.PagerInfo.RecordCount = result.TotalCount;
            }
        }
    复制代码

     

    3、在WPF应用中实现嵌套明细展示效果

    我们这里继续介绍另外一个DataGrid的效果,通过明细展示的方式显示其中一条记录相关联的表格信息,有时候也可以看成是主从关联信息。

    单我们单击其中一条记录的时候,展示嵌套表格,展示详细的明细信息,如下效果所示。

    这个效果主要是通过定义DataGrid.RowDetailsTemplate进行明细内容的处理的。例如我们定义明细的模板如下所示,其实也就是显示另外一个表格信息。

    复制代码
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <DataGrid
                MaxHeight="500"
                hc:DataGridAttach.ShowRowNumber="True"
                AlternatingRowBackground="LightBlue"
                AutoGenerateColumns="False"
                HeadersVisibility="Column"
                IsReadOnly="True"
                RowHeaderWidth="60"
                ScrollViewer.VerticalScrollBarVisibility="Auto"
                SelectionUnit="FullRow">
                <DataGrid.Columns>
                    <DataGridTextColumn
                        MinWidth="120"
                        Binding="{Binding Name}"
                        Header="显示名称" />
                    <DataGridTemplateColumn Width="80" Header="图标">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ui:SymbolIcon
                                    Width="32"
                                    FontSize="32"
                                    Symbol="{Binding Icon}" />
                            DataTemplate>
                        DataGridTemplateColumn.CellTemplate>
                    DataGridTemplateColumn>
                    <DataGridTextColumn
                        Width="80"
                        Binding="{Binding Seq}"
                        Header="排序" />
                    <DataGridTextColumn
                        Width="100"
                        Binding="{Binding FunctionId}"
                        Header="功能ID" />
                DataGrid.Columns>
    
            DataGrid>
        DataTemplate>
    DataGrid.RowDetailsTemplate>
    复制代码

    Xaml的结构如下所示。

    另外,我们在视图模型中除了定义一级的数据记录外,还定义一个嵌套记录集合对象,如下所示。

    复制代码
            /// 
            /// 编辑的数据列表
            /// 
            [ObservableProperty]
            private ObservableCollection? menuItems;
    
    
            /// 
            /// 指定父级的子级数据列表
            /// 
            [ObservableProperty]
            private ObservableCollection? detailItems;
    复制代码

    这样我们在行选择变化的时候,重新获得明细的记录,然后绑定显示事件即可,如下代码所示。

    复制代码
       /// 
       /// 记录行变化的时候,触发明细记录的获取处理
       /// 
       private async void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
       {
           var datagrid = sender as DataGrid;
           if (datagrid != null)
           {
               var item = datagrid!.SelectedItem as MenuInfo;
               if (item != null)
               {
                   await ViewModel.GetDetailList(item.Id);
               }
           }
       }
    复制代码

    而在页面初始化的时候,我们可以构造一个事件,用来绑定明细记录的绑定显示处理。

    复制代码
        //明细记录可见性变化的时候,触发数据的绑定处理事件
        this.grid.RowDetailsVisibilityChanged += (s, e) =>
        {
            var datagrid = s as DataGrid;
            if (datagrid != null)
            {
                var DetailsDataGrid = e.DetailsElement as DataGrid;
                if(DetailsDataGrid != null)
                {
                    DetailsDataGrid.ItemsSource = viewModel.DetailItems;
                }
            }
        };
    复制代码

    这样就可以正常的显示嵌套明细的记录了。

     

    链接附注

    如对我们的代码生成工具有兴趣,可以到官网下载使用《代码生成工具Database2Sharp》。

    如需了解我们官网对《SqlSugar开发框架》的介绍,可以参考《SqlSugar开发框架》了解。

    如需阅读我们对于《SqlSugar开发框架》文章介绍,可以参考博客园的随笔标签《SqlSugar随笔 , WPF随笔》学习了解。

     

  • 相关阅读:
    在PowerBI中提取IFC文件中的数据
    Web 基础概念
    mysql设置max_sp_recursion_depth,sql_mode
    火狐浏览器翻译页面功能如何设置
    SpringMVC 程序开发
    黑马瑞吉外卖之售卖状态的更改
    狂神说MybatisPlus学习笔记
    2022年CCPC桂林站C题Array Concatenation
    【业务功能篇91】微服务-springcloud-多线程-线程池执行顺序
    VSCode使用
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/17989031