WPF之浅谈数据模板(DataTemplate)
数据模板有什么用
简而言之,数据模板能让你更方便、更灵活的显示你的各类数据。只有你想不到,没有它做不到的(感觉有点夸张,实践之后,你就觉得一点不夸张 ??)。
直接对比下效果:
无数据模板
应用了数据模板
好了,下面我们一步一步来看看数据模板如何做到化腐朽为神奇的!
一些前置条件
-
假设你已了解了MVVM设计模式
-
假设你已了解了一些数据绑定知识
-
假设你已了解了一些样式知识
代码准备
-
首先准备一个Model,代码如下:
public class Employee { public string Name { get; set; } public Sex Sex { get; set; } public string Job { get; set; } public string Department { get; set; } public string Email { get; set; } } public enum Sex { Male, Female }
-
在准备好ViewModel,代码如下:
public class MainViewModel: BindableBase { private IEnumerable<Employee> _employees; public IEnumerable<Employee> Employees { get => _employees; set => SetProperty(ref _employees, value); } public MainViewModel() { Employees = new List<Employee>() { new Employee() {Name="张明",Department="技术售后部",Job="售后工程师",Sex=Sex.Male,Email="Zhang.San@wpf.com"}, new Employee() {Name="葛倩",Department="人事部",Job="招聘专员",Sex=Sex.Female,Email="Ge.Qian@wpf.com"}, new Employee() {Name="王小伟",Department="研发部",Job="高级软件工程师",Sex=Sex.Male,Email="Wang.Xiaowei@wpf.com"}, }; } }
没有数据模板
准备好没有使用数据模板的view的xaml代码
<Window x:Class="WpfPractice.DataTemplateDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfPractice.DataTemplateDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox ItemsSource="{Binding Employees}"
HorizontalContentAlignment="Stretch">
</ListBox>
</Grid>
</Window>
运行下程序,就会出现这样的界面
熟悉.Net的同学,应该看出来每一项显示的是对象的ToString
方法返回的值。因为我们集合中存放的是复杂类型的对象,如果没有数据模板,ListBox
默认就会用ToString
去显示。而ToString
方法默认返回的就是对象的类型限定名。
既然了解到这个原理,那我们重载实现下ToString
方法
public class Employee
{
public string Name { get; set; }
public Sex Sex { get; set; }
public string Job { get; set; }
public string Department { get; set; }
public string Email { get; set; }
public override string ToString()
{
return $"{Name},{Job},{Department}";
}
}
再次运行程序,结果如下
这次算是显示出一些有用信息了,但这样的UI体验,未免太差。如何让我们的数据呈现更加吸引人呢?下面就轮到数据模板大显身手了。
应用数据模板
直接上应用了数据模板的xaml代码
<Window x:Class="WpfPractice.DataTemplateDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfPractice.DataTemplateDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox ItemsSource="{Binding Employees}"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Employee}">
<Border Padding="5" BorderThickness="1" BorderBrush="Gray" CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" FontSize="18" FontWeight="Black"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Job}"/>
<TextBlock Text="{Binding Department}"/>
<TextBlock Text="{Binding Email}"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
其实数据模板就是把对象的属性绑定到不同的UI控件上,然后通过合理的布局,就能显示让数据显示的更加美观了。
怎么样?效果完全就不一样了,到这里,相信同学你应该能get到数据模板的作用了!当然这个只是数据模板的最基本用法,其实数据模板还有其他更强大的功能。比如可以通过数据模板让男性员工的名字显示成淡蓝色,女性的名字显示成淡绿色。这个功能下面触发器的部分会介绍。
我们还是接着数据模板定义这部分内容,我们是通过重写了ListBox.ItemTemplate
来定义数据模板的,但如果在其他控件我们也要显示这样,岂不是在定义一遍这个数据模板?这样明显不符合我们代码复用的原则。还好,在wpf中,我们可以通过资源的方式来定义通用的数据模板,代码如下
<Window x:Class="WpfPractice.DataTemplateDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfPractice.DataTemplateDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Employee}">
<Border Padding="5" BorderThickness="1" BorderBrush="Gray" CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" FontSize="18" FontWeight="Black"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Job}"/>
<TextBlock Text="{Binding Department}"/>
<TextBlock Text="{Binding Email}"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Employees}"
HorizontalContentAlignment="Stretch">
</ListBox>
</Grid>
</Window>
此时我们发现,并不需要重新定义ListBox.ItemTemplate
,但运行结果和上面保持一致!
数据触发器
前面我们提到可以通过数据模板让男性员工的名字显示成淡蓝色,女性的名字显示成淡绿色,其实就可以通过数据触发器来实现这样的功能。
这里简单说下触发器的作用,更详细的去看[微软的官方文档](DataTrigger Class (System.Windows) | Microsoft Learn)。触发器就是当绑定的数据满足某个条件时,可以去设置一些控件的属性值,或者执行一些动作(例如动画)。
基于触发器原理,实现的代码如下
<Window.Resources>
<DataTemplate DataType="{x:Type local:Employee}">
<Border Padding="5" BorderThickness="1" BorderBrush="Gray" CornerRadius="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txtName" VerticalAlignment="Center" Text="{Binding Name}" FontSize="18" FontWeight="Black"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Job}"/>
<TextBlock Text="{Binding Department}"/>
<TextBlock Text="{Binding Email}"/>
</StackPanel>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Sex}" Value="Male">
<Setter TargetName="txtName" Property="Foreground" Value="LightBlue"/>
</DataTrigger>
<DataTrigger Binding="{Binding Sex}" Value="Female">
<Setter TargetName="txtName" Property="Foreground" Value="LightGreen"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
运行结果
我们可以看到是通过修改显示名字的TextBlock
的字体颜色来实现我们需求的,其实我们可以同时设置多个控件的属性来满足更复杂的需求的。
到这里,浅谈数据模板就接近尾声了,所谓浅谈,其实把数据模板的核心用法都覆盖到了,在实际项目开发中,都是基于这些知识的灵活应用!
最后
奉上源代码 https://gitee.com/liuww06/wpfpractice/tree/master/src/WpfPractice.DataTemplateDemo