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 类表示根据 GroupDescriptions 由 CollectionView 对象创建的组。
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学习交流。