原文:
背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组
背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组
作者:webabcd
介绍
背水一战 Windows 10 之 控件(集合类 - ItemsControl)
- 项模板选择器
- 数据分组
示例
1、ItemsControl 的项模板选择器
Controls/CollectionControl/ItemsControlDemo/ItemsControlDemo3.xaml
<Page x:Class="Windows10.Controls.CollectionControl.ItemsControlDemo.ItemsControlDemo3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.CollectionControl.ItemsControlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:common="using:Windows10.Common"> <Page.Resources> <!-- DataTemplate - 数据模板 --> <DataTemplate x:DataType="common:Employee" x:Key="DataTemplateMale"> <Grid Background="Blue"> <TextBlock Text="{x:Bind Name}" /> </Grid> </DataTemplate> <DataTemplate x:DataType="common:Employee" x:Key="DataTemplateFemale"> <Grid Background="Pink"> <TextBlock Text="{x:Bind Name}" /> </Grid> </DataTemplate> <!-- 自定义数据模板选择器(参见 code-behind 中的代码) --> <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector" DataTemplate1="{StaticResource DataTemplateMale}" DataTemplate2="{StaticResource DataTemplateFemale}" /> </Page.Resources> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10" Orientation="Horizontal"> <!-- ItemsControl - 集合控件 ItemTemplateSelector - 每个数据项的数据模板选择器(如果指定了 ItemTemplate 则此配置无效) --> <ListView Name="itemsControl" Margin="5" Width="400" Height="400" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{x:Bind Employees}" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"> </ListView> </StackPanel> </Grid> </Page>
Controls/CollectionControl/ItemsControlDemo/ItemsControlDemo3.xaml.cs
/* * ItemsControl - 集合控件(继承自 Control, 请参见 /Controls/BaseControl/ControlDemo/) * * * 本例用于演示 ItemsControl 如何通过 item 的不同而使用不同的数据模板 */ using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows10.Common; namespace Windows10.Controls.CollectionControl.ItemsControlDemo { public sealed partial class ItemsControlDemo3 : Page { public ObservableCollection<Employee> Employees { get; set; } = TestData.GetEmployees(100); public ItemsControlDemo3() { this.InitializeComponent(); } } // 自定义 DataTemplateSelector(数据模板选择器) // 可以实现在 runtime 时,根据 item 的不同选择不同的数据模板 public class MyDataTemplateSelector : DataTemplateSelector { // 数据模板 1(配置在 xaml 端) public DataTemplate DataTemplate1 { get; set; } // 数据模板 2(配置在 xaml 端) public DataTemplate DataTemplate2 { get; set; } // 根据 item 的数据的不同,指定的不同的模板 protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { var employee = item as Employee; if (employee == null || employee.IsMale) return DataTemplate1; // 男员工用数据模板 1 return DataTemplate2; // 女员工用数据模板 2 // 如果想直接返回指定的资源也是可以的(但是不灵活),类似:return (DataTemplate)Application.Current.Resources["DataTemplateMale"]; } } }
2、ItemsControl 的数据分组
Controls/CollectionControl/ItemsControlDemo/ItemsControlDemo4.xaml
<Page x:Class="Windows10.Controls.CollectionControl.ItemsControlDemo.ItemsControlDemo4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Controls.CollectionControl.ItemsControlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <!-- GroupStyle - 组样式 HidesIfEmpty - 空组是否隐藏 HeaderContainerStyle - 组标题的容器样式 HeaderTemplate - 组标题的模板 HeaderTemplateSelector - 组标题的模板选择器 注: ListView 的 Group 的 HeaderContainer 是 ListViewHeaderItem, GridView 的 Group 的 HeaderContainer 是 GridViewHeaderItem ListViewHeaderItem 和 GridViewHeaderItem 均继承自 ListViewBaseHeaderItem, ListViewBaseHeaderItem 继承自 ContentControl --> <GroupStyle x:Key="GroupStyle1" HeaderTemplate="{StaticResource DataTemplateGroupHeader}"> <GroupStyle.HeaderContainerStyle> <Style TargetType="ListViewHeaderItem"> <Setter Property="Background" Value="Blue" /> </Style> </GroupStyle.HeaderContainerStyle> </GroupStyle> <GroupStyle x:Key="GroupStyle2" HeaderTemplate="{StaticResource DataTemplateGroupHeader}"> <GroupStyle.HeaderContainerStyle> <Style TargetType="ListViewHeaderItem"> <Setter Property="Background" Value="Orange" /> </Style> </GroupStyle.HeaderContainerStyle> </GroupStyle> <DataTemplate x:Key="DataTemplateGroupHeader"> <TextBlock Text="{Binding Title}" /> </DataTemplate> <!-- 自定义 GroupStyle 选择器(参见 code-behind 中的代码) --> <local:MyGroupStyleSelector x:Key="MyGroupStyleSelector" GroupStyle1="{StaticResource GroupStyle1}" GroupStyle2="{StaticResource GroupStyle2}" /> </Page.Resources> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <!-- ItemsControl - 集合控件 ItemsPanel - 用于指定 items 的布局控件,任何 Panel 类型的布局控件均可,所有 items 将在 Panel 内显示(Panel 是所有 items 的容器) 给 ItemsControl 用的,可虚拟化的布局控件有:ItemsStackPanel, ItemsWrapGrid, VirtualizingStackPanel, WrapGrid. 请参见:/Controls/CollectionControl/ItemsControlDemo/LayoutControl/ GroupStyle - 组样式 GroupStyleSelector - 组样式选择器 --> <ListView Name="listView" Margin="5" Width="400" Height="400" HorizontalAlignment="Left" ItemsSource="{x:Bind MyData.View}" GroupStyleSelector="{StaticResource MyGroupStyleSelector}" SelectionChanged="listView_SelectionChanged"> <!-- <ListView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock Text="{Binding Title}" /> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> --> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Title}" Foreground="Purple" /> </DataTemplate> </ListView.ItemTemplate> <ListView.ItemsPanel> <ItemsPanelTemplate> <ItemsStackPanel /> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView> <TextBlock Name="lblMsg" Margin="5" /> </StackPanel> </Grid> </Page>
Controls/CollectionControl/ItemsControlDemo/ItemsControlDemo4.xaml.cs
/* * ItemsControl - 集合控件(继承自 Control, 请参见 /Controls/BaseControl/ControlDemo/) * IsGrouping - 当前 ItemsControl 显示的是否是分组数据(只读) * DependencyObject GroupHeaderContainerFromItemContainer(DependencyObject itemContainer) - 获取指定 ItemContainer 的 HeaderContainer * * * 本例用于演示如何通过 ItemsControl 显示分组数据 * * 注:本例是用 ListView 来演示数据分组的,用 GridView 做数据分组的示例请参见 /Index.xaml */ using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; using Windows10.Common; namespace Windows10.Controls.CollectionControl.ItemsControlDemo { public sealed partial class ItemsControlDemo4 : Page { public CollectionViewSource MyData { get { XElement root = XElement.Load("SiteMap.xml"); var items = LoadData(root); // 构造数据源 CollectionViewSource source = new CollectionViewSource(); source.IsSourceGrouped = true; source.Source = items; source.ItemsPath = new PropertyPath("Items"); return source; } } public ItemsControlDemo4() { this.InitializeComponent(); this.Loaded += ItemsControlDemo4_Loaded; } private void ItemsControlDemo4_Loaded(object sender, RoutedEventArgs e) { lblMsg.Text = "IsGrouping: " + listView.IsGrouping.ToString(); } private async void listView_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0 && listView.ContainerFromItem(e.AddedItems[0]) != null) { // 获取选中数据的 HeaderContainer ListViewHeaderItem headerContainer = listView.GroupHeaderContainerFromItemContainer(listView.ContainerFromItem(e.AddedItems[0])) as ListViewHeaderItem; NavigationModel headerNavigationModel = headerContainer.Content as NavigationModel; await new MessageDialog($"header: {headerNavigationModel.Title}").ShowAsync(); } } // 解析 xml 数据 private List<NavigationModel> LoadData(XElement root) { if (root == null) return null; var items = from n in root.Elements("node") select new NavigationModel { Title = (string)n.Attribute("title"), Url = (string)n.Attribute("url"), Items = LoadData(n) }; return items.ToList(); } } // 自定义 MyGroupStyleSelector(GroupStyle 选择器) // 可以实现在 runtime 时,根据 group 的不同选择不同的 GroupStyle public class MyGroupStyleSelector : GroupStyleSelector { static bool temp = false; // GroupStyle 1(配置在 xaml 端) public GroupStyle GroupStyle1 { get; set; } // GroupStyle 2(配置在 xaml 端) public GroupStyle GroupStyle2 { get; set; } protected override GroupStyle SelectGroupStyleCore(object group, uint level) { // 我这里测试,group 要么是 null 要么是 DependencyObject,level 总是 0 // 利用这个变量,来演示如何让不同的 group 使用不同的 GroupStyle temp ^= true; if (temp) return GroupStyle1; return GroupStyle2; // 如果想直接返回指定的资源也是可以的(但是不灵活),类似:return (GroupStyle)Application.Current.Resources["GroupStyle1"]; } } }
OK
[源码下载]