首页 > 其他分享 >在WPF应用中实现DataGrid的分组显示,以及嵌套明细展示效果

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

时间:2024-01-26 12:56:19浏览次数:26  
标签:展示 明细 DataGrid 嵌套 分组 所示 gridView1 WPF

我在前面随笔《在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后,设置分组信息即可,如下代码所示。

/// <summary>
/// 查询处理
/// </summary>
[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就是视图模型基类函数的查询获得数据的处理方式。

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

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

    /// <summary>
    /// 根据分页和查询条件查询,请求数据
    /// </summary>
    /// <returns></returns>
    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的结构如下所示。

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

        /// <summary>
        /// 编辑的数据列表
        /// </summary>
        [ObservableProperty]
        private ObservableCollection<MenuInfo>? menuItems;


        /// <summary>
        /// 指定父级的子级数据列表
        /// </summary>
        [ObservableProperty]
        private ObservableCollection<MenuInfo>? detailItems;

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

   /// <summary>
   /// 记录行变化的时候,触发明细记录的获取处理
   /// </summary>
   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;
            }
        }
    };

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

 

标签:展示,明细,DataGrid,嵌套,分组,所示,gridView1,WPF
From: https://www.cnblogs.com/wuhuacong/p/17989031

相关文章

  • C# WPF 开发一个 Emoji 表情查看软件
    微软在发布Windows11系统的时候,发布过一个开源的Emoji表情fluentui-emoji。因为我经常需要里面的一些表情图片,在仓库一个个查找特别的不方便,所以我做了一个表情查看器,可以很方便的查看所有表情,同时可以定位到表情文件的位置。这套fluentui-emoji表情一共有1545个。开......
  • wpf第十一个画面
    主要使用了Grid控件、Image控件、Textblock控件、Textbox控件、ComboBox控件、Button控件、TabControl控件、DataGrid控件、 Margin属性来设置当前控件与容器控件的间距Margin=“20”//left,top,right和bottom都设置为20Margin=“20,10”//left,right设置为20,top,bottom设置为10......
  • wpf_绑定两个ViewModel
    Juster.Music\MainWindow.xaml.csnamespaceJuster.Music{///<summary>///InteractionlogicforMainWindow.xaml///</summary>publicpartialclassMainWindow:Window{publicMainWindow(){......
  • 基于CefSharp、WPF开发浏览器项目----系列文章
    基于CefSharp、WPF开发浏览器项目基于CefSharp开发浏览器(十一)增添F11、F12功能基于CefSharp开发浏览器(十)CefSharp.Wpf中文输入法偏移处理基于CefSharp开发浏览器(九)浏览器历史记录弹窗面板基于CefSharp开发浏览器(八)浏览器收藏夹栏基于CefSharp开发浏览器(七)浏览器收藏夹菜单基......
  • Python web crawler(2.1)多循环嵌套练习
    写个函数,传入(书名:book,标题:tittle,内容:content),要求在book文件夹下(不存在则创建),创建每个tittle.txt文件,写入content内容importosdefsave_to_file(folder_book,title,content):#如果文件夹不存在,则创建ifnotos.path.exists(folder_book):os.makedirs(......
  • 基于CefSharp开发浏览器(十)浏览器CefSharp.Wpf中文输入法偏移处理
    一、前言两年多来未曾更新博客,最近一位朋友向我咨询中文输入法问题。具体而言,他在使用CefSharpWPF版本时遇到了一个问题,即输入法突然出现在屏幕的左上角。在这里记录下处理这个问题的过程,希望能够帮助到其他遇到类似问题的开发者。让我们一起来探讨如何解决能更好的处理CefSharp......
  • FluentValidation在C# WPF中的应用
    1.引言在.NET开发领域,FluentValidation以其优雅、易扩展的特性成为开发者进行属性验证的首选工具。它不仅适用于Web开发,如MVC、WebAPI和ASP.NETCORE,同样也能完美集成在WPF应用程序中,提供强大的数据验证功能。本文将深入探讨如何在C#WPF项目中运用FluentValidation进行属性验......
  • 集合嵌套
    1//集合嵌套2publicstaticvoidmain(String[]args){3//要求程序记录每个学生选择的情况4//使用一个map集合嵌套5Map<String,List<String>>data=newHashMap<>();67//将学生选择的数据存入进去8......
  • WPF动态绑定隐藏或显示DataGrid一列(转)
    原文连接一、添加一個FrameworkElement的代理<Window.Resources><FrameworkElementx:Key="ProxyElement"DataContext="{Binding}"/></Window.Resources> 二、用一個不可見的ContentControl綁定上一步的FrameworkElement代理<ContentControlV......
  • WPF UI线程卡顿的一些理解
    WPFMVVM模型中线程分为UI线程(主线程)和其他线程(新建的线程)UI线程主要工作:1、负责响应外部的输入事件2、负责渲染UI界面,包括绘图、动画等其他线程:1、负责进行数据采集处理2、负责进行消息的分发 实际的工作中我们要合理使用线程,特别是大量的数据展示,图表动画渲染。不然很......