集合控件的自定义设计由 DataTemplate 管理。 数据模板定义每个项的布局和样式,并将该标记应用于集合中的每个项。 本文介绍如何使用 DataTemplateSelector 对集合应用不同的数据模板,并根据选择的某些项属性或值选择要使用的数据模板。
重要 API: DataTemplateSelector、 DataTemplate
DataTemplateSelector 是启用自定义模板选择逻辑的类。 它允许你定义用于集合中某些项的数据模板的规则。 为实现此逻辑,您可以在后台代码中创建一个 DataTemplateSelector 的子类,并定义逻辑以决定适用于不同项类别的数据模板(例如,某种特定类型的项或具有特定属性值的项等)。 在 XAML 文件的 Resources 部分中声明此类的实例,以及将要使用的数据模板的定义。 可以使用一个 x:Key 值来标识这些资源,可在 XAML 中引用它们。
先决条件
何时不使用 DataTemplateSelector
通常,不应为 ListView 或 GridView 中的每个项提供完全不同的布局/样式 - 这会导致 DataTemplateSelector 的使用不佳,并会对性能产生负面影响。
通过绑定某些属性,可以仅使用一个数据模板来控制列表项的视觉显示的某些元素。 例如,项可以通过绑定到数据模板中的图标源属性来具有不同的图标,并为每个项提供该图标源属性的不同值。 这比使用 DataTemplateSelector 更好的性能。
何时使用 DataTemplateSelector
如果要在一个集合控件中使用多个数据模板,则应创建 DataTemplateSelector 。 通过 A DataTemplateSelector ,你可以灵活地使某些项目脱颖而出,同时仍然使项目保持类似的布局。 在很多用例中,DataTemplateSelector 非常有用,在一些方案中,最好重新思考所使用的控件和策略。
集合控件通常绑定到同一类型的项目集合。 但是,即使项的类型可能相同,它们可能具有某些属性的不同值或表示不同的含义。 某些项可能比其他项更重要,或者一个项目可能特别重要或不同,并且需要直观地脱颖而出。在这些情况下,DataTemplateSelector 将非常有用。
还可以绑定到包含不同类型的项的集合 - 绑定集合可以混合使用字符串、ints、自定义类对象等。 这使得 DataTemplateSelector 特别有用,因为它可以根据项的对象类型分配不同的数据模板。
下面是使用数据模板选择器时的一些示例:
- 表示 ListView 中不同级别的员工 - 每个员工类型/级别可能需要不同的颜色背景才能轻松区分。
- 使用 GridView 展示的产品库中的销售项目可能需要红色背景或不同的字体颜色,以便从常规价格的产品中脱颖而出。
- 使用 FlipView 在照片库中展示优胜者/精选照片。
- 需要以不同的方式表示 ListView 中的负/正数,或短字符串/长字符串。
创建 DataTemplateSelector
创建数据模板选择器时,可以在代码中定义模板选择逻辑,并在 XAML 中定义数据模板。
代码隐藏组件
若要使用数据模板选择器,请先在后台代码中创建 DataTemplateSelector (派生自它的类)的子类。 在类中,将每个模板声明为类的属性。 然后,重写 SelectTemplateCore 方法以包含自己的模板选择逻辑。
下面是名为 DataTemplateSelector 的简单MyDataTemplateSelector子类的示例。
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Normal { get; set; }
public DataTemplate Accent { get; set; }
protected override DataTemplate SelectTemplateCore(object item)
{
if ((int)item % 2 == 0)
{
return Normal;
}
else
{
return Accent;
}
}
}
该 MyDataTemplateSelector 类派生自 DataTemplateSelector 该类,首先定义两个 DataTemplate 对象: Normal 和 Accent。 这些声明目前为空声明,但会用 XAML 文件中的标记“填充”。
SelectTemplateCore 方法接受一个项对象(即每个集合项),并根据特定条件重写规则返回 DataTemplate。 在这种情况下,如果项是奇数,它便接收Accent 数据模板;如果项是偶数,则接收Normal 数据模板。
XAML 组件
其次,必须在 XAML 文件的 Resources 节中创建此新 MyDataTemplateSelector 类的实例。 所有资源都需要一个 x:Key,您可以使用它将集合控件的 ItemTemplateSelector 属性进行绑定(在后面的步骤中)。 还可以创建两个 DataTemplate 对象实例,并在资源部分定义其布局。 您将这些数据模板分配给在MyDataTemplateSelector类中声明的Accent和Normal属性。
下面是所需的 XAML 资源和标记示例:
<Page.Resources>
<DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}">
<TextBlock Text="{x:Bind}" />
</Button>
</DataTemplate>
<DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}">
<TextBlock Text="{x:Bind}" />
</Button>
</DataTemplate>
<l:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
Normal="{StaticResource NormalItemTemplate}"
Accent="{StaticResource AccentItemTemplate}"/>
</Page.Resources>
如上所示,这两个数据模板Normal和Accent被定义 - 它们都以按钮的形式显示项,但Accent数据模板对背景使用主题色画笔,而Normal数据模板则使用灰色画笔(SystemChromeLowColor)。 然后,把这两个数据模板分配给在 C# 后置代码中创建的 MyDataTemplateSelector 类的属性 Normal 和 Accent 的 DataTemplate 对象。
最后一步是将你的DataTemplateSelector绑定到集合控件的ItemTemplateSelector属性(在本例中为 ListView)。 这取代了向属性分配值 ItemTemplate 的需求。
<ListView x:Name = "TestListView"
ItemsSource = "{x:Bind NumbersList}"
ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
</ListView>
代码编译后,每个集合项都将通过在 MyDataTemplateSelector 中重写的 SelectTemplateCore 方法运行,并使用相应的 DataTemplate 进行呈现。
重要
使用DataTemplateSelector与ItemsRepeater时,将DataTemplateSelector绑定到ItemTemplate属性。
ItemsRepeater 没有属性 ItemTemplateSelector 。
DataTemplateSelector 性能注意事项
使用 ListView 或 GridView 配合大数据集时,滚动和平移性能可能会成为一个问题。 为了保持大型集合的性能良好,可以采取一些步骤来提高数据模板的性能。 ListView 和 GridView UI 优化中更详细地介绍了这些内容。
- 每个项的元素减少 - 将数据模板中的 UI 元素数保持在合理的最小值。
- 使用异构集合进行容器再利用
- 使用 ChoosingItemContainer 事件 - 此事件是将不同数据模板用于不同项的高性能方法。 若要获得最佳性能,应针对特定数据优化缓存和选择数据模板。
- 使用 项模板选择器 - 由于项模板选择器可能对性能产生影响,在某些情况下应避免使用项模板选择器
DataTemplateSelector。