WPF DataTemplate 数据模板
DataTemplate 顾名思义,数据模板,在 wpf 中使用非常频繁。
它一般用在带有 DataTemplate 依赖属性的控件中,如 ContentControl、集合控件 ListBox、ItemsControl 、TabControls 等。
1. 非集合控件中使用
<UserControl.Resources>
<DataTemplate x:Key="MyDataTemplate">
<Grid
Width="100"
Height="40"
Background="DeepPink" />
</DataTemplate>
</UserControl.Resources>
在前端代码中,应用这个数据模板,
<ContentControl ContentTemplate="{StaticResource MyDataTemplate}" />
显示如下:
2. 集合控件中使用
以 ListBox 为例,
假设 ListBox 绑定数据源为下面的 MyItems ,
public class DataTemplateViewModel
{
public IList<string> MyItems { get; }
public DataTemplateViewModel()
{
MyItems = new List<string>() { "Tom~", "Jerry~"};
}
}
<ListBox
Grid.Column="1"
ItemsSource="{Binding MyItems}" />
在不设置数据模板的情况下,默认就是显示字符串,
新增一个数据模板,
<UserControl.Resources>
<DataTemplate x:Key="MyDataTemplate">
<Grid
Width="100"
Height="40"
Background="DeepPink">
<TextBlock Text="{Binding .}" Foreground="Yellow" />
</Grid>
</DataTemplate>
</UserControl.Resources>
并应用该模板后,
<ListBox
Grid.Column="1"
ItemTemplate="{StaticResource MyDataTemplate}"
ItemsSource="{Binding MyItems}" />
显示为,
通过上面的例子,我们可以知道,数据模板,可以用来自定义数据展示的方式,包括:格式、效果、样式等。
3. DataTempate 其它用法
3.1 自动匹配数据类型
上面演示的集合中使用 DataTemplate 的方式,数据类型相对简单。实际开发中经常要根据不同数据类型,展示不同数据样式。
假设申明一个图形接口,
public interface IShape
{
string Color { get; }
}
一个圆、矩形类各自实现该接口,
public class Circle : IShape
{
public string Color { get; }
public Circle(string color)
{
Color = color;
}
}
public class Rectange : IShape
{
public string Color { get; }
public Rectange(string color)
{
Color = color;
}
}
集合 Shapes 中包含这些图形实例,
public class DataTemplateViewModel
{
public IList<IShape> Shapes { get; }
public DataTemplateViewModel()
{
Shapes = new List<IShape>()
{
new Circle("#CC0066"),
new Rectange("#009900"),
};
}
}
设置 DataTemplate 的 DataType
属性(不设置 x:key),就可以根据图形类型,自动应用对应数据模板,
<ListBox
Grid.Column="1"
ItemsSource="{Binding Shapes}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type views:Circle}">
<Ellipse Width="60" Height="60" Fill="{Binding Color}" />
</DataTemplate>
<DataTemplate DataType="{x:Type views:Rectange}">
<Rectangle Width="60" Height="60" Fill="{Binding Color}" />
</DataTemplate>
</ListBox.Resources>
</ListBox>
效果如下,
3.2 DataTemplateSelector
使用 DataTemplateSelector (模板选择器)也可以同样实现上面的效果。
我们只需要继承 DataTemplateSelector 类,并重载其 SelectTemplate 方法,
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate CircleTemplate { get; set; }
public DataTemplate RectTemplate { get; set; }
public DataTemplate EmptyTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is Circle)
{
return CircleTemplate;
}
else if (item is Rectange)
{
return RectTemplate;
}
return EmptyTemplate;
}
}
数据模板 + 选择器 前端定义,这时就要设置 DataTemplate 的 x:key 了,
<UserControl.Resources>
<DataTemplate x:Key="Circle.DataTemplate">
<Ellipse Width="60" Height="60" Fill="{Binding Color}" />
</DataTemplate>
<DataTemplate x:Key="Rectangle.DataTemplate">
<Rectangle Width="60" Height="60" Fill="{Binding Color}" />
</DataTemplate>
<DataTemplate x:Key="Empty.DataTemplate">
<Grid Width="60" Height="60" Background="Black" />
</DataTemplate>
<views:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
CircleTemplate="{StaticResource Circle.DataTemplate}"
RectTemplate="{StaticResource Rectangle.DataTemplate}"
EmptyTemplate="{StaticResource Empty.DataTemplate}" />
</UserControl.Resources>
应用选择器,
<ListBox
Grid.Column="1"
ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"
ItemsSource="{Binding Shapes}">
</ListBox>
新增一个 null 元素配合实验,
Shapes = new List<IShape>()
{
new Circle("#CC0066"),
new Rectange("#009900"),
null,
};
显示效果,