我们在将一个数据集合绑定到列表控件时,有时候想根据不同的数据类型,显示为不同的效果。
例如将一个文件夹集合绑定到ListBox时,系统文件夹和普通文件夹分别显示为不同的效果,就可以使用模板选择器功能。
WPF提供了一个模板选择器类型DataTemplateSelector ,它可以根据数据对象和数据绑定元素来选择 DataTemplate。
使用方法
创建一个类,继承自DataTemplateSelector,并重写SelectTemplate方法。
类似下面这样
1 using System.Windows;
2 using System.Windows.Controls;
3
4 namespace SDKSample
5 {
6 public class TaskListDataTemplateSelector : DataTemplateSelector
7 {
8 public override DataTemplate
9 SelectTemplate(object item, DependencyObject container)
10 {
11 FrameworkElement element = container as FrameworkElement;
12
13 if (element != null && item != null && item is Task)
14 {
15 Task taskitem = item as Task;
16
17 if (taskitem.Priority == 1)
18 return
19 element.FindResource("importantTaskTemplate") as DataTemplate;
20 else
21 return
22 element.FindResource("myTaskTemplate") as DataTemplate;
23 }
24
25 return null;
26 }
27 }
28 }
下面我们使用ListBox 和TreeView进行演示
ListBox的使用示例
我们先定义如下的数据模型
1 public class FileData
2 {
3 public string FileName { get; set; }
4 }
5
6 public class FileData1 : FileData
7 {
8 public string FileData1Property { get; set; }
9 }
10
11 public class FileData2:FileData
12 {
13 public string FileData2Property { get; set; }
14 }
然后定义一个资源字典,分别在里面定义两种数据的数据模板
1 <DataTemplate x:Key="FileData1Datatemplate">
2 <Grid>
3 <Grid.ColumnDefinitions>
4 <ColumnDefinition/>
5 <ColumnDefinition/>
6 </Grid.ColumnDefinitions>
7 <Label Content="{Binding FileName}" FontSize="20" Foreground="Green"></Label>
8 <Label Content="{Binding FileData1Property}" Grid.Column="1" VerticalAlignment="Center"></Label>
9 </Grid>
10 </DataTemplate>
11
12 <DataTemplate x:Key="FileData2Datatemplate">
13 <Grid>
14 <Grid.ColumnDefinitions>
15 <ColumnDefinition/>
16 <ColumnDefinition/>
17 </Grid.ColumnDefinitions>
18 <Label Content="{Binding FileName}" FontSize="16" Foreground="Red"></Label>
19 <Label Content="{Binding FileData2Property}" Grid.Column="1" VerticalAlignment="Center"></Label>
20 </Grid>
21 </DataTemplate>
添加测试数据
1 List<FileData> fileDatas = new List<FileData>();
2 FileData1 fileData1 = new FileData1();
3 fileData1.FileName = "1.jpg";
4 fileData1.FileData1Property = "1.jpg property";
5 FileData2 fileData2 = new FileData2();
6 fileData2.FileName = "2.jpg";
7 fileData2.FileData2Property = "2.jpg property";
8 fileDatas.Add(fileData1);
9 fileDatas.Add(fileData2);
10 this.listbox.ItemsSource = fileDatas;
然后再为ListBox 设置DataTemplateSelector
1 this.listbox.ItemTemplateSelector = new ItemDataTemplateSelector();
运行效果如下:
TreeView的使用示例
这里我们定义一个磁盘和文件夹的数据类型,一个磁盘对象可以包含多个文件夹
1 public class Disk
2 {
3 public string DiskName { get; set; }
4
5 public List<Folder> Folders { get; set; } = new List<Folder>();
6 }
7
8 public class Folder
9 {
10 public string FullPath { get; set; }
11
12 public long Size { get; set; }
13 }
使用使用HierarchicalDataTemplate 为TreeView设置层级的数据模板
针对Disk 的HierarchicalDataTemplate
1 <HierarchicalDataTemplate x:Key="DiskDatatemplate" ItemsSource="{Binding Folders}" DataType="{x:Type local:Disk}">
2 <Grid>
3 <Grid.ColumnDefinitions>
4 <ColumnDefinition Width="25"/>
5 <ColumnDefinition/>
6 </Grid.ColumnDefinitions>
7
8 <Image Source="disk.png" Height="25"></Image>
9 <Label Content="{Binding DiskName}" Grid.Column="1"></Label>
10 </Grid>
11 </HierarchicalDataTemplate>
针对Folder 的HierarchicalDataTemplate
1 <HierarchicalDataTemplate x:Key="FolderDatatemplate" DataType="{x:Type local:Folder}">
2 <Grid>
3 <Grid.ColumnDefinitions>
4 <ColumnDefinition Width="25"/>
5 <ColumnDefinition Width="auto"/>
6 <ColumnDefinition/>
7 </Grid.ColumnDefinitions>
8
9 <Image Source="folder.png" Height="25"></Image>
10 <Label Content="{Binding FullPath}" Grid.Column="1"></Label>
11 <Label Content="{Binding Size}" Grid.Column="2"></Label>
12 </Grid>
13 </HierarchicalDataTemplate>
然后我们创建一个DataTemplateSelector ,根据不同的数据类型返回不同的HierarchicalDataTemplate
这里仅做演示,实际使用时推荐使用switch并增加错误检测。
1 public class NodeDataTemplateSelector : DataTemplateSelector
2 {
3 public override DataTemplate SelectTemplate(object item, DependencyObject container)
4 {
5 if (item is Disk)
6 return Application.Current.FindResource("DiskDatatemplate") as DataTemplate;
7 else
8 return Application.Current.FindResource("FolderDatatemplate") as DataTemplate;
9 }
10 }
添加测试数据
1 Disk disk = new Disk();
2 disk.DiskName = "D:\\";
3
4 Folder folder = new Folder();
5 folder.FullPath = "D:\\Software";
6 folder.Size = 1024;
7 disk.Folders.Add(folder);
8
9 Disk disk2 = new Disk();
10 disk2.DiskName = "E:\\";
11
12 Folder folder2 = new Folder();
13 folder2.FullPath = "E:\\Documents";
14 folder2.Size = 2048;
15 disk2.Folders.Add(folder2);
16
17 List<Disk> disks = new List<Disk>();
18 disks.Add(disk);
19 disks.Add(disk2);
20
21 this.treeview.ItemsSource = disks;
为TreeView 设置DataTemplateSelector
1 this.treeview.ItemTemplateSelector = new NodeDataTemplateSelector();
运行效果
示例代码
参考资料:
DataTemplateSelector 类 (System.Windows.Controls) | Microsoft Learn