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

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

WPF Samples中的示例

在WPF Samples中有一个关于Grouping的Demo。

该Demo结构如下:

MainWindow.xaml如下:

<Window x:Class="Grouping.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:Grouping"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" SizeToContent="Height">
    <StackPanel>
        <StackPanel.Resources>
            <XmlDataProvider x:Key="MyTasks" XPath="Tasks/Task">
                <x:XData>
                    <Tasks xmlns="">
                        <Task Name="Groceries" Priority="2" Type="Home">
                            <Description>Pick up Groceries and Detergent</Description>
                        </Task>
                        <Task Name="Laundry" Priority="2" Type="Home">
                            <Description>Do Laundry</Description>
                        </Task>
                        <Task Name="Email" Priority="1" Type="Work">
                            <Description>Email Clients</Description>
                        </Task>
                        <Task Name="Clean" Priority="3" Type="Work">
                            <Description>Clean my office</Description>
                        </Task>
                        <Task Name="Dinner" Priority="1" Type="Home">
                            <Description>Get ready for family reunion</Description>
                        </Task>
                        <Task Name="Proposals" Priority="2" Type="Work">
                            <Description>Review new budget proposals</Description>
                        </Task>
                    </Tasks>
                </x:XData>
            </XmlDataProvider>
        </StackPanel.Resources>
        <TextBlock Margin="12,5,5,0" FontSize="20" Text="My Task List"/>
        <CheckBox Margin="10,5,5,10" Checked="AddGrouping"
              Unchecked="RemoveGrouping">Group by task type</CheckBox>
        <ItemsControl Margin="10" Name="myItemsControl"
                  ItemsSource="{Binding Source={StaticResource MyTasks}}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <DataTemplate.Resources>
                        <Style TargetType="TextBlock">
                            <Setter Property="FontSize" Value="18"/>
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                        </Style>
                    </DataTemplate.Resources>
                    <Grid>
                        <Ellipse Fill="Silver"/>
                        <StackPanel>
                            <TextBlock Margin="3,3,3,0"
                         Text="{Binding XPath=@Name}"/>
                            <TextBlock Margin="3,0,3,7"
                         Text="{Binding XPath=@Priority}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Control.Width" Value="100"/>
                    <Setter Property="Control.Margin" Value="5"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock FontWeight="Bold" FontSize="15"
                         Text="{Binding Path=Name}"/>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ItemsControl.GroupStyle>
        </ItemsControl>
    </StackPanel>
</Window>

其中:

<StackPanel.Resources>
            <XmlDataProvider x:Key="MyTasks" XPath="Tasks/Task">
                <x:XData>
                    <Tasks xmlns="">
                        <Task Name="Groceries" Priority="2" Type="Home">
                            <Description>Pick up Groceries and Detergent</Description>
                        </Task>
                        <Task Name="Laundry" Priority="2" Type="Home">
                            <Description>Do Laundry</Description>
                        </Task>
                        <Task Name="Email" Priority="1" Type="Work">
                            <Description>Email Clients</Description>
                        </Task>
                        <Task Name="Clean" Priority="3" Type="Work">
                            <Description>Clean my office</Description>
                        </Task>
                        <Task Name="Dinner" Priority="1" Type="Home">
                            <Description>Get ready for family reunion</Description>
                        </Task>
                        <Task Name="Proposals" Priority="2" Type="Work">
                            <Description>Review new budget proposals</Description>
                        </Task>
                    </Tasks>
                </x:XData>
            </XmlDataProvider>
        </StackPanel.Resources>

使用XmlDataProvider来加载和绑定XML数据。

<ItemsControl Margin="10" Name="myItemsControl"
                  ItemsSource="{Binding Source={StaticResource MyTasks}}">

将MyTasks绑定到ItemsControl。

<DataTemplate>
                    <DataTemplate.Resources>
                        <Style TargetType="TextBlock">
                            <Setter Property="FontSize" Value="18"/>
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                        </Style>
                    </DataTemplate.Resources>
                    <Grid>
                        <Ellipse Fill="Silver"/>
                        <StackPanel>
                            <TextBlock Margin="3,3,3,0"
                         Text="{Binding XPath=@Name}"/>
                            <TextBlock Margin="3,0,3,7"
                         Text="{Binding XPath=@Priority}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>

设置数据模板。

跟本次介绍的主题Grouping有关的内容如下:

<ItemsControl.GroupStyle>
    <GroupStyle>
         <GroupStyle.HeaderTemplate>
             <DataTemplate>
                   <TextBlock FontWeight="Bold" FontSize="15"
                       Text="{Binding Path=Name}"/>
              </DataTemplate>
          </GroupStyle.HeaderTemplate>
     </GroupStyle>
 </ItemsControl.GroupStyle>

ItemsControl.GroupStyle获取定义每个级别的组的外观的 GroupStyle 对象集合。

GroupStyle如下所示:

public class GroupStyle : INotifyPropertyChanged
    {
       
        public static readonly ItemsPanelTemplate DefaultGroupPanel;       
        public GroupStyle();
        public static GroupStyle Default { get; }
        [DefaultValue(0)]
        public int AlternationCount { get; set; }    
        [DefaultValue(null)]
        public Style ContainerStyle { get; set; }
        [DefaultValue(null)]
        public StyleSelector ContainerStyleSelector { get; set; }
        [DefaultValue(null)]
        public string HeaderStringFormat { get; set; }
        [DefaultValue(null)]
        public DataTemplate HeaderTemplate { get; set; }     
        [DefaultValue(null)]
        public DataTemplateSelector HeaderTemplateSelector { get; set; }
        [DefaultValue(false)]
        public bool HidesIfEmpty { get; set; }
        public ItemsPanelTemplate Panel { get; set; }
        protected event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e);
    }
}

这里设置了GroupStyle.HeaderTemplate,这个元素定义了分组头的数据模板。数据模板决定了分组头的具体显示方式。

<TextBlock FontWeight="Bold" FontSize="15"
                       Text="{Binding Path=Name}"/>

这里的Name指的是CollectionViewGroup 类的Name属性。

CollectionViewGroup 类表示根据 GroupDescriptionsCollectionView 对象创建的组。

MainWindow.cs如下:

public partial class MainWindow : Window
 {
     private CollectionView _myView;
     public MainWindow()
     {
         InitializeComponent();
     }
     private void AddGrouping(object sender, RoutedEventArgs e)
     {
         _myView = (CollectionView) CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
         if (_myView.CanGroup)
         {
             var groupDescription
                 = new PropertyGroupDescription("@Type");
             _myView.GroupDescriptions.Add(groupDescription);
         }
     }
     private void RemoveGrouping(object sender, RoutedEventArgs e)
     {
         _myView = (CollectionView) CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
         _myView.GroupDescriptions.Clear();
     }
 }

只包含两个事件处理程序。

进行分组是这样写的:

private void AddGrouping(object sender, RoutedEventArgs e)
     {
         _myView = (CollectionView) CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
         if (_myView.CanGroup)
         {
             var groupDescription
                 = new PropertyGroupDescription("@Type");
             _myView.GroupDescriptions.Add(groupDescription);
         }
     }
_myView = (CollectionView) CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);

虽然CollectionViewSource本身不是一个静态类,但它提供了一个静态方法GetDefaultView,这个方法用于获取与特定数据源关联的默认视图。这种设计允许开发者不必实例化CollectionViewSource对象就能访问和操作数据源的视图。

var groupDescription
     = new PropertyGroupDescription("@Type");
 _myView.GroupDescriptions.Add(groupDescription);

PropertyGroupDescription类描述使用属性名作为条件对项进行分组。

使用的是这个构造函数:

= new PropertyGroupDescription("@Type");

在XML和XPath的上下文中,@符号用于引用元素的属性。

这样就实现了基于Type属性进行分组。

private void RemoveGrouping(object sender, RoutedEventArgs e)
  {
      _myView = (CollectionView) CollectionViewSource.GetDefaultView(myItemsControl.ItemsSource);
      _myView.GroupDescriptions.Clear();
  }

取消分组将_myView.GroupDescriptions清空即可。

该Demo的效果如下:

分组前:

分组后:

代码来源

[WPF-Samples/Data Binding/Grouping at main · microsoft/WPF-Samples (github.com)]

欢迎关注微信公众号:DotNet学习交流。

目录
相关文章
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据
C#实现上位机开发,串口通信,读写串口数据并处理16进制数据。在自动化、物联网以及工业控制行业中,上位机开发是一项重要的技能。本教程主要介绍使用C#进行上位机开发,重点在于串口通信和数据处理。
206 82
C#集合数据去重的5种方式及其性能对比测试分析
C#集合数据去重的5种方式及其性能对比测试分析
39 11
C#集合数据去重的5种方式及其性能对比测试分析
C#集合数据去重的5种方式及其性能对比测试分析
56 10
C#如何处理上亿级数据的查询效率
C#如何处理上亿级数据的查询效率
84 1
C# WPF 中 外部图标引入iconfont,无法正常显示问题 【小白记录】
本文介绍了在C# WPF应用程序中引入外部iconfont图标时可能遇到的显示问题及其解决方法:1) 检查资源路径和引入格式是否正确,确保字体文件引用格式为“#xxxx”,并正确指向字体文件位置;2) 确保图标资源被包含在程序集中,通过设置字体文件的生成操作为Resource(资源)来实现。
C# WPF 中 外部图标引入iconfont,无法正常显示问题 【小白记录】
C# + WPF 音频播放器 界面优雅,体验良好
【9月更文挑战第18天】这是一个用 C# 和 WPF 实现的音频播放器示例,界面简洁美观,功能丰富。设计包括播放/暂停按钮、进度条、音量控制滑块、歌曲列表和专辑封面显示。功能实现涵盖音频播放、进度条控制、音量调节及歌曲列表管理。通过响应式设计、动画效果、快捷键支持和错误处理,提升用户体验。可根据需求扩展更多功能。
192 3
|
5月前
|
枚举与结构体的应用:C#中的数据组织艺术
在C#编程中,枚举(`enum`)和结构体(`struct`)是非常重要的数据类型。枚举用于定义命名常量集合,提高代码可读性;结构体则封装相关数据字段,适合小型数据集。本文从基本概念入手,探讨它们的使用技巧、常见问题及解决方案,帮助开发者更好地利用这些特性构建健壮的应用程序。
77 8
C#数据分表核心代码
C#数据分表核心代码
63 0
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
945 0
硬件交互新体验:WPF与传感器的完美结合——从初始化串行端口到读取温度数据,一步步教你打造实时监控的智能应用
【8月更文挑战第31天】本文通过详细教程,指导Windows Presentation Foundation (WPF) 开发者如何读取并处理温度传感器数据,增强应用程序的功能性和用户体验。首先,通过`.NET Framework`的`Serial Port`类实现与传感器的串行通信;接着,创建WPF界面显示实时数据;最后,提供示例代码说明如何初始化串行端口及读取数据。无论哪种传感器,只要支持串行通信,均可采用类似方法集成到WPF应用中。适合希望掌握硬件交互技术的WPF开发者参考。
110 0