WPF/C#:显示分组数据的两种方式

wpf · 浏览次数 : 0

小编点评

前言 本文将介绍在WPF中处理分组显示需求时,可供选择的两种方案。首先,我们将讨论基于ICollectionView的方案,然后是基于IGrouping的方案。最后,我们将回顾本文内容并简要总结。 一、基于ICollectionView的方案 1. CS代码 使用CollectionViewSource类获取集合的默认视图,并创建一个PropertyGroupDescription对象。将创建的PropertyGroupDescription对象添加到CollectionViewSource的GroupDescriptions属性中。 ```csharp public GroupDemoViewModel() { People = new ObservableCollection { // 初始化People集合 }; CollectionViewSource viewSource = CollectionViewSource.GetDefaultView(People); viewSource.GroupDescriptions.Add(new PropertyGroupDescription("Class")); } ``` 2. XAML代码 在XAML文件中,除了常规的数据绑定之外,还需要添加ListView的GroupStyle,并设置GroupStyle.HeaderTemplate。 ```xml ``` 二、基于IGrouping的方案 1. CS代码 使用LINQ的GroupBy方法对People集合进行分组。此方法根据People对象的Class属性值将集合分成多个组。 ```csharp public GroupDemoViewModel() { People = new ObservableCollection { // 初始化People集合 }; GroupedPeople = People.GroupBy(x => x.Class); } ``` 2. XAML代码 在XAML代码中,使用Expander控件绑定分组的Key属性。在Expander控件内部,包含一个ListView控件,用于展示每个分组中的数据项。 ```xml ``` 三、归纳总结 本文介绍了在WPF中处理分组显示需求时的两种方案。首先,我们讨论了基于ICollectionView的方案,包括CS代码和XAML代码的实现。接着,我们介绍了基于IGrouping的方案,同样包括CS代码和XAML代码的实现。这两种方案都可以实现对数据进行分组显示,但具体实现方式和展示效果可能有所不同。在选择合适的方案时,可以根据实际需求和项目特点进行权衡。

正文

前言

本文介绍自己在遇到WPF对数据进行分组显示的需求时,可以选择的两种方案。一种方案基于ICollectionView,另一种方案基于IGrouping

基于ICollectionView实现

相关cs代码:

[ObservableProperty]
private ObservableCollection<People> people;

public GroupDemoViewModel()
{
    People = new ObservableCollection<People>
    {
        new People { Name = "小一", Class = "1班" },
        new People { Name = "小二", Class = "2班" },
        new People { Name = "王五", Class = "1班" },
        new People { Name = "小红", Class = "2班" },
        new People { Name = "小绿", Class = "1班" },
        new People { Name = "小刚", Class = "2班" },
    };
   
    MyView = CollectionViewSource.GetDefaultView(People);
    var groupDescription
        = new PropertyGroupDescription("Class");
    MyView.GroupDescriptions.Add(groupDescription); 
}

这段代码使用了WPF中的CollectionViewSourcePropertyGroupDescription类来对数据进行分组。

CollectionViewSource是一个用于提供数据视图的类,它允许你对数据进行排序、筛选和分组。

GetDefaultView方法返回一个默认视图,该视图是对People集合的包装。这个视图可以用于在UI中显示数据,并且可以应用各种视图操作(如排序、筛选和分组)。

PropertyGroupDescription是一个用于定义分组规则的类。这里创建了一个新的PropertyGroupDescription对象,并指定分组依据的属性为Class,这意味着数据将根据这意味着数据将根据People集合中每个对象的Class属性值进行分组。

xaml相关代码:

<ui:ListView ItemsSource="{Binding MyView}">
    <ui:ListView.ItemTemplate>
        <DataTemplate >
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}" Margin="5"/>
                <TextBlock Text="{Binding Class}" Margin="5"/>
            </StackPanel>
        </DataTemplate>
    </ui:ListView.ItemTemplate>
    <ui:ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="16"/>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ui:ListView.GroupStyle>
</ui:ListView>

GroupStyleGroupStyle.HeaderTemplate是用来自定义分组头部的显示方式。

GroupStyle: 这是一个用于定义分组样式的元素。它允许你为ui:ListView中的每个分组自定义外观和行为。在这个元素内部,你可以定义头部模板(HeaderTemplate)、容器样式(ContainerStyle)等。
GroupStyle.HeaderTemplate: 这个元素定义了分组头部的模板。通过这个模板,你可以自定义分组头部的外观。

实现的效果如下所示:

image-20240619122143726

基于IGrouping实现

在将数据分组时,我个人比较喜欢使用Linq的GroupBy。

相关cs代码如下:

  [ObservableProperty]
  private ObservableCollection<People> people;

  public IEnumerable<IGrouping<string?,People>> GroupedPeople { get; set; }

  public GroupDemoViewModel()
  {
      People = new ObservableCollection<People>
      {
          new People { Name = "小一", Class = "1班" },
          new People { Name = "小二", Class = "2班" },
          new People { Name = "王五", Class = "1班" },
          new People { Name = "小红", Class = "2班" },
          new People { Name = "小绿", Class = "1班" },
          new People { Name = "小刚", Class = "2班" },
      };

      GroupedPeople = People.GroupBy(x => x.Class);    
  }
 GroupedPeople = People.GroupBy(x => x.Class); 

这行代码使用LINQ的GroupBy方法对People集合进行分组。

GroupBy(x => x.Class)的作用是根据People对象的Class属性的值将这个集合分成多个组。每个组是一个包含有相同Class值的People对象集合。这里的x代表People集合中的每一个People对象,x => x.Class是一个lambda表达式,指定了分组的依据是People对象的Class属性。

GroupBy方法的结果是一个IEnumerable<IGrouping<string?, People>>类型的对象。IGrouping<string?, People>接口表示一个分组,其中string?是分组键的类型(在这个例子中是Class属性的类型),People是集合中元素的类型。每个IGrouping<string?, People>对象包含一个键(Key属性,即Class的值)和一个集合(包含所有具有该Class值的People对象)。

相关xaml代码如下:

 <ui:ListView ItemsSource="{Binding GroupedPeople}">
     <ui:ListView.ItemTemplate>
         <DataTemplate >
             <Expander Header="{Binding Key}">
                 <ui:ListView ItemsSource="{Binding}">
                     <ItemsControl.ItemTemplate>
                         <DataTemplate>
                             <StackPanel Orientation="Horizontal">
                                 <TextBlock Text="{Binding Name}" Margin="5"/>
                                 <TextBlock Text="{Binding Class}" Margin="5"/>
                             </StackPanel>
                         </DataTemplate>
                     </ItemsControl.ItemTemplate>
                 </ui:ListView>
             </Expander>
         </DataTemplate>
     </ui:ListView.ItemTemplate>
 </ui:ListView>

使用了Expander控件。

Expander是WPF中的一个控件,中文通常翻译为“扩展器”或“可折叠控件”。它是一个容器控件,允许用户通过点击标题栏来展开或折叠其内容区域。这种控件在用户界面设计中非常有用,可以用来隐藏或显示详细信息,从而节省屏幕空间。

实现效果如下所示:

image-20240619123207859

image-20240619123228203

回顾

本文介绍了遇到WPF对数据进行分组显示的需求时,可以选择的两种方案。一种方案基于ICollectionView,另一种方案基于IGrouping

基于ICollectionView的方案,在cs代码中通过CollectionViewSource.GetDefaultView方法获得集合的默认视图,创建一个PropertyGroupDescription类,ICollectionViewGroupDescriptions属性添加创建的PropertyGroupDescription对象。在xaml代码中,除了一般的数据绑定外,还添加了ListView.GroupStyle,设置了 GroupStyle.HeaderTemplate

基于IGrouping的方案,在cs代码中,使用LinqGroupBy方法对People集合进行分组。在xaml代码中在ListView的数据模板中使用Expander控件绑定分组的Key属性,在Expander控件中再包含一个ListView控件,绑定每个分组中的数据项。

与WPF/C#:显示分组数据的两种方式相似的内容:

WPF/C#:显示分组数据的两种方式

前言 本文介绍自己在遇到WPF对数据进行分组显示的需求时,可以选择的两种方案。一种方案基于ICollectionView,另一种方案基于IGrouping。 基于ICollectionView实现 相关cs代码: [ObservableProperty] private ObservableColl

WPF/C#:如何将数据分组显示

WPF Samples中的示例 在WPF Samples中有一个关于Grouping的Demo。 该Demo结构如下: MainWindow.xaml如下:

WPF/C#:在DataGrid中显示选择框

前言 在使用WPF的过程中可能会经常遇到在DataGrid的最前或者最后添加一列选择框的需求,今天跟大家分享一下,在自己的项目中是如何实现的。 整体实现效果如下: 如果对此感兴趣,可以接下来看具体实现部分。 实践 假设数据库中的模型如下: public class Person { public i

WPF/C#:实现导航功能

前言 在WPF中使用导航功能可以使用Frame控件,这是比较基础的一种方法。前几天分享了wpfui中NavigationView的基本用法,但是如果真正在项目中使用起来,基础的用法是无法满足的。今天通过wpfui中的mvvm例子来说明在wpfui中如何通过依赖注入与MVVM模式使用导航功能。实践起来

WPF/C#:在WPF中如何实现依赖注入

本文先介绍依赖注入的概念,再解释为什么要进行依赖注入,最后通过 WPF Gallery 这个项目学习如何在WPF中使用依赖注入。

WPF/C#:如何实现拖拉元素

前言 在Canvas中放置了一些元素,需要能够拖拉这些元素,在WPF Samples中的DragDropObjects项目中告诉了我们如何实现这种效果。 效果如下所示: 拖拉过程中的效果如下所示: 具体实现 xaml页面 我们先来看看xaml:

WPF/C#:BusinessLayerValidation

BusinessLayerValidation介绍 BusinessLayerValidation,即业务层验证,是指在软件应用程序的业务逻辑层(Business Layer)中执行的验证过程。业务逻辑层是应用程序架构中的一个关键部分,负责处理与业务规则和逻辑相关的操作。业务层验证的主要目的是确保数

WPF/C#:数据绑定到方法

在WPF Samples中有一个关于数据绑定到方法的Demo,该Demo结构如下: 运行效果如下所示: 来看看是如何实现的。 先来看下MainWindow.xaml中的内容:

WPF/C#:程序关闭的三种模式

ShutdownMode枚举类型介绍 ShutdownMode是一个枚举类型,它定义了WPF应用程序的关闭方式。这个枚举类型有三个成员: OnLastWindowClose:当最后一个窗口关闭或者调用System.Windows.Application.Shutdown方法时,应用程序会关闭。 On

C# WPF 将第三方DLL嵌入 exe

没成功,只是做个记录,后面再研究 希望将第三方的 HandyControl.dll 嵌入到 exe 中,这样不用发多个文件给别人 ![image](https://img2023.cnblogs.com/blog/80824/202308/80824-20230804153348542-538869