WPF应用实战开发指南 - 如何实现DataGrid分组显示及嵌套明细展示效果

📅 2026/7/18 10:00:24
WPF应用实战开发指南 - 如何实现DataGrid分组显示及嵌套明细展示效果
在之前一些文章中介绍了Winform程序中对表格内容进行了分组的展示在WPF应用中同样也可以对表格的内容进行分组展示不过处理方式和Winform有所差异本文同样基于SqlSugar开发框架的基础上实现在WPF应用中实现DataGrid的分组显示以及嵌套明细展示效果。PS给大家推荐一个C#开发可以用到的界面组件——DevExpress WPF它拥有120个控件和库将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。回顾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的添加处理即可实现汇总效果的展示。在WPF应用中实现DataGrid的分组显示在WPF应用中数据的显示通过DataGrid控件进行展示默认是没有分组效果的如果需要分组效果需要定制表格的分组样式才能达到效果。同样基于SqlSugar开发框架的基础上基于原料表的数据展示实现在WPF应用中实现DataGrid的分组显示实现的效果如下所示。我们这里根据【类别】字段来进行分组统一其中分组样式在XAML上定义如下所示。DataGrid.GroupStyle GroupStyle GroupStyle.ContainerStyle Style TargetType{x:Type GroupItem} Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type GroupItem} Expander IsExpandedTrue Expander.Header StackPanel OrientationHorizontal TextBlock FontWeightBold Text类别 / TextBlock FontWeightBold 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 FontWeightBold Text{Binding Name} / /DataTemplate /GroupStyle.HeaderTemplate /GroupStyle /DataGrid.GroupStyle如果我们需要控件的虚拟化处理提高显示性能那么设置下虚拟化处理属性即可。DataGridx:Namegrid Grid.Row1 hc:DataGridAttach.ShowRowNumberTrue AutoGenerateColumnsFalse HeadersVisibilityAll IsReadOnlyTrue ItemsSource{Binding ViewModel.Items} MouseDoubleClickDataGrid_MouseDoubleClick RowHeaderWidth60 SelectionChangedDataGrid_SelectionChanged SelectionModeExtended VerticalScrollBarVisibilityAuto VirtualizingPanel.IsVirtualizingTrue VirtualizingPanel.IsVirtualizingWhenGroupingTrue 表格的字段如没有特殊处理我们用常用的定义效果即可如下所示。DataGrid.Columns DataGridTextColumn WidthSizeToCells MinWidth100 Binding{Binding Id} HeaderID编号 / DataGridTextColumn WidthSizeToCells MinWidth100 Binding{Binding Category} Header类别 / DataGridTextColumn WidthSizeToCells MinWidth100 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; } }在WPF应用中实现嵌套明细展示效果我们这里继续介绍另外一个DataGrid的效果通过明细展示的方式显示其中一条记录相关联的表格信息有时候也可以看成是主从关联信息。单我们单击其中一条记录的时候展示嵌套表格展示详细的明细信息如下效果所示。这个效果主要是通过定义DataGrid.RowDetailsTemplate进行明细内容的处理的。例如我们定义明细的模板如下所示其实也就是显示另外一个表格信息。DataGrid.RowDetailsTemplate DataTemplate DataGrid MaxHeight500 hc:DataGridAttach.ShowRowNumberTrue AlternatingRowBackgroundLightBlue AutoGenerateColumnsFalse HeadersVisibilityColumn IsReadOnlyTrue RowHeaderWidth60 ScrollViewer.VerticalScrollBarVisibilityAuto SelectionUnitFullRow DataGrid.Columns DataGridTextColumn MinWidth120 Binding{Binding Name} Header显示名称 / DataGridTemplateColumn Width80 Header图标 DataGridTemplateColumn.CellTemplate DataTemplate ui:SymbolIcon Width32 FontSize32 Symbol{Binding Icon} / /DataTemplate /DataGridTemplateColumn.CellTemplate /DataGridTemplateColumn DataGridTextColumn Width80 Binding{Binding Seq} Header排序 / DataGridTextColumn Width100 Binding{Binding FunctionId} Header功能ID / /DataGrid.Columns /DataGrid /DataTemplate /DataGrid.RowDetailsTemplateXaml的结构如下所示。另外我们在视图模型中除了定义一级的数据记录外还定义一个嵌套记录集合对象如下所示。/// summary /// 编辑的数据列表 /// /summary [ObservableProperty] private ObservableCollectionMenuInfo? menuItems; /// summary /// 指定父级的子级数据列表 /// /summary [ObservableProperty] private ObservableCollectionMenuInfo? 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; } } };这样就可以正常的显示嵌套明细的记录了。本文转载自博客园 - 伍华聪