WPF数据绑定之数据模板

WPF 数据模板模型为定义数据的表示提供了很大的灵活性。WPF 控件具有支持自定义数据表示的内置功能。本主题首先演示如何定义 DataTemplate,然后介绍其他数据模板功能,例如根据自定义逻辑选择模板和支持显示分层数据。

先决条件
本主题重点介绍数据模板功能,不介绍数据绑定概念。有关基本数据绑定概念的信息,请参见数据绑定概述。

DataTemplate 用于数据表示,是 WPF 样式和模板模型提供的许多功能中的一种。

另外,了解Resources也很重要,它实际上是有关使对象(例如,Style. 和 DataTemplate)成为可重用对象的内容。

数据模板基础

为了说明 DataTemplate 为什么这么重要,让我们演示一个数据绑定的示例。在本示例中,有一个绑定到 Task 对象列表的 ListBox。每个 Task 对象都有 TaskName (string)、Description (string)、Priority (int) 和类型 TaskType 的属性,它是一个 Enum,其值为 Home 和 Work。

没有 DataTemplate
如果没有 DataTemplate,我们的 ListBox 当前具有如下外观:


由于没有任何特定说明,ListBox 在尝试显示集合中的对象时,默认情况下会调用 ToString。因此,如果 Task 对象重写 ToString 方法,则 ListBox 显示基础集合中每个源对象的字符串表示形式。

例如,如果 Task 类以这种方式重写 ToString 方法,其中 name 是 TaskName 属性的字段:

则 ListBox 如下所示:


但是,这是受到限制的,并不灵活。另外,如果您要绑定到 XML 数据,您不能重写 ToString。

定义简单 DataTemplate
该解决方案定义 DataTemplate。这样做的一种方式是将 ListBox 的 ItemTemplate 属性设置为 DataTemplate。DataTemplate 中指定的内容变成数据对象的可视结构。以下 DataTemplate 相当简单。我们要给出的说明是:每项显示为 StackPanel 中的三个 TextBlock 元素。每个 TextBlock 元素绑定到 Task 类的一个属性。

本主题中的示例的基础数据是 CLR 对象的一个集合。如果您要绑定到 XML 数据,基本概念相同,但是语法稍微不同。例如,不是让 Path=TaskName,而是将 XPath 设置为 @TaskName(如果 TaskName 是 XML 节点的属性)。

现在 ListBox 如下所示:


将 DataTemplate 创建为资源
在上面的示例中,我们定义了 DataTemplate 内联。更为常见的是在资源部分中定义它,以使其成为一个可重用的对象,如下面的示例所示:

现在,您可以将 myTaskTemplate 用作资源,如下面的示例所示:

因为 myTaskTemplate 是资源,所以您现在可以在具有采用 DataTemplate 类型的属性的其他控件中使用它。如上所述,对于 ItemsControl 对象(例如 ListBox),它是 ItemTemplate 属性。对于 ContentControl 对象,它是 ContentTemplate 属性。

DataType 属性
DataTemplate 类具有 DataType 属性,该属性非常类似于 Style. 类的 TargetType 属性。因此,在上述示例中不需要为 DataTemplate 指定 x:Key,您可以执行以下操作:

此 DataTemplate 自动应用于所有 Task 对象。请注意,在这种情况下,x:Key 是隐式设置的。因此,如果要为此 DataTemplate 分配一个 x:Key 值,则要重写隐式 x:Key 并且不会自动应用 DataTemplate。

如果要将 ContentControl 绑定到 Task 对象的集合,则 ContentControl 不会自动使用以上 DataTemplate。这是因为在 ContentControl 上绑定需要更多的信息来区分是要绑定到整个集合还是要绑定到单个对象。如果 ContentControl 要跟踪对 ItemsControl 类型的选择,您可以将 ContentControl 绑定的 Path 属性设置为“/”以表示您对当前项感兴趣。有关示例,请参见如何:绑定到集合并基于选择显示信息。否则,需要通过设置 ContentTemplate 属性显式指定 DataTemplate。

DataType 属性在您拥有不同类型数据对象的 CompositeCollection 时尤其有用。
向 DataTemplate 添加更多信息
当前,数据显示了必要的信息,但是还可以显示更多信息。让我们通过添加 Border、Grid 和一些用于描述要显示的数据的 TextBlock 来显示更多信息。

下面的屏幕快照使用此已修改的 DataTemplate 来显示 ListBox。

我们可以在 ListBox 上将 HorizontalContentAlignment 设置为 Stretch 来确保项的宽度占据整个空间:

HorizontalContentAlignment 属性设置为 Stretch 后,ListBox 现在如下所示:


使用 DataTrigger 来应用属性值
当前表示不会告诉我们某个 Task 是家庭任务还是办公室任务。记住 Task 对象拥有类型为 TaskType 的 TaskType 属性,该类型是一个枚举,其值可以为 Home 和 Work。

在下面的示例中,DataTrigger 将 border 元素的 BorderBrush 设置为 Yellow(如果 TaskType 属性为 TaskType.Home)。

应用程序现在如下所示。家庭任务的边界显示为黄色,办公室任务的边界显示为浅绿色。


在此示例中,DataTrigger 使用 Setter 来设置属性值。触发器类也拥有 EnterActions 和 ExitActions 属性,这些属性允许您开始一组操作,例如动画操作。而且,还有一个 MultiDataTrigger 类,它允许您根据多个数据绑定属性值应用更改。

达到相同效果的另一种方式是将 BorderBrush 属性绑定到 TaskType 属性,然后使用值转换器根据 TaskType 值来返回颜色。有关类似示例,请参见如何:改变 ListView 中各行的背景色。就性能而言,使用转换器创建上述效果的效率要高一点。另外,创建自己的转换器使您可以获得更多的灵活性,因为您提供的是自己的逻辑。最后,您选择的技术取决于您当时的具体情况和您的偏好。

 

DataTemplate 中有哪些内容?
在前面的示例中,我们使用 DataTemplate.Triggers 属性将触发器放入 DataTemplate 中。触发器的 Setter 设置 DataTemplate 中元素(Border 元素)的属性值。但是,如果您的 Setters 相关属性不是当前 DataTemplate 中元素的属性,则使用 Style(用于 ListBoxItem 类)设置属性更合适(如果您要绑定的控件是 ListBox)。例如,如果您想要在鼠标指向某一项时让您的 Trigger 对该项的 Opacity 值进行动画处理,则需要在 ListBoxItem 样式中定义触发器。

通常需要注意:DataTemplate 会应用于每个生成的 ListBoxItem(有关它实际应用的方式和场合的更多信息,请参见 ItemTemplate 页)。DataTemplate 仅与数据对象的表示和外观有关。在大多数情况下,所有其他表示方面(例如,项在被选中时的外观或 ListBox 排列项的方式)不在 DataTemplate 定义范围内。

根据数据对象的属性选择 DataTemplate
在 DataType 属性一节中,我们讨论了您可以针对不同的数据对象定义不同的数据模板。这在您拥有不同类型的 CompositeCollection 或不同类型的项集合时尤其有用。在使用 DataTrigger 来应用属性值一节中,我们演示了如果您拥有相同类型的数据对象集合,您可以创建 DataTemplate,然后根据每个数据对象的属性值使用触发器来应用更改。虽然触发器允许您应用属性值或启动动画,但是它们无法让您灵活重构数据对象的结构。在某些情况下,可能需要您为类型相同但属性不同的数据对象创建其他 DataTemplate。

例如,当 Task 对象的 Priority 值为 1 时,您可能需要为它指定完全不同的外观,以给予您自己一个提醒。在这种情况下,您需要创建 DataTemplate 来显示高优先级的 Task 对象。让我们将以下 DataTemplate 添加到资源部分:

请注意,此示例使用 DataTemplate.Resources 属性。DataTemplate 中的元素共享该部分中定义的资源。

若要提供逻辑以根据数据对象的 Priority 值选择要使用的 DataTemplate,需要创建 DataTemplateSelector 的子类并重写 SelectTemplate 方法。在下面的示例中,SelectTemplate 方法提供逻辑以根据 Priority 属性的值返回适当的模板。可以在封装 Window 元素的资源中找到要返回的模板。

然后,我们可以将 TaskListDataTemplateSelector 声明为资源:

若要使用模板选择器资源,请将其分配到 ListBox 的 ItemTemplateSelector 属性。ListBox 为基础集合中的每一项调用 TaskListDataTemplateSelector 的 SelectTemplate 方法。该调用会将数据对象作为项参数来传递。然后,将由该方法返回的 DataTemplate 应用于该数据对象。

使用模板选择器后,ListBox 现在如下所示:



这正是此示例要得到的结果。

 

对 ItemsControl 进行样式和模板处理
即使 ItemsControl 不是 DataTemplate 所用于的唯一控件类型,将 ItemsControl 绑定到集合仍然很常见。在 DataTemplate 中有哪些内容一节中,我们讨论了您的 DataTemplate 定义应当仅与数据表示相关。为了明确何时不适合使用 DataTemplate,有必要了解 ItemsControl 提供的不同样式和模板属性。下面的示例旨在演示这些属性中每一个属性的功能。本示例中的 ItemsControl 绑定到与前面示例中的 Tasks 集合。为便于演示,本示例中的样式和模板都进行了内联声明。

下面是该示例在呈现时的屏幕快照:


请注意,您可以使用 ItemTemplateSelector,而不是 ItemTemplate。请参考上一节的示例。同样,可以选择使用 ItemContainerStyleSelector,而不是 ItemContainerStyle。

这里未显示 ItemsControl 的其他两个与样式相关的属性,它们是 GroupStyle. 和 GroupStyleSelector。

对分层数据的支持
到目前为止,我们仅讨论如何绑定和显示单个集合。某些时候,您要绑定的集合包含其他集合。HierarchicalDataTemplate 类专用于 HeaderedItemsControl 类型以显示这样的数据。在下面的示例中,ListLeagueList 是 League 对象的列表。每个 League 对象都有一个 Name 和 Division 对象的集合。每个 Division 都有一个 Name 和 Team 对象的集合,并且每个 Team 对象都有一个 Name。

该示例演示通过使用 HierarchicalDataTemplate,您可以轻松地显示包含其他列表的列表数据。下面是该示例的一个屏幕快照。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF ListBox 绑定模板指的是在 ListBox 中使用数据绑定绑定数据源,并使用自定义的模板来呈现数据。 以下是实现 WPF ListBox 绑定模板的步骤: 1. 创建数据源:创建一个集合类,用于存储数据源。 2. 绑定数据源:使用 ListBox 的 ItemsSource 属性将数据绑定到 ListBox 控件上。 3. 创建数据模板:通过创建一个 DataTemplate 对象来定义自定义模板。 4. 应用模板:使用 ListBox 的 ItemTemplate 属性将模板应用到 ListBox 控件上。 下面是一个示例代码,演示如何实现 WPF ListBox 绑定模板: ``` <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ListBox ItemsSource="{Binding Students}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Age}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window> ``` 在上述代码中,我们创建了一个 ListBox 控件,并将它的 ItemsSource 属性绑定到一个名为 Students 的集合类上。然后,我们创建了一个 DataTemplate 对象,并在其中定义了一个 StackPanel 和两个 TextBlock 控件,用于显示每个学生的姓名和年龄。最后,我们将模板应用到 ListBox 中,以便呈现数据。 注意:在代码中,我们使用了数据绑定和 MVVM 模式,这里不再赘述。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值