WPF之浅谈数据模板(DataTemplate)
阅读原文时间:2023年08月11日阅读:1

数据模板有什么用

简而言之,数据模板能让你更方便、更灵活的显示你的各类数据。只有你想不到,没有它做不到的(感觉有点夸张,实践之后,你就觉得一点不夸张 )。

直接对比下效果:

无数据模板

应用了数据模板

好了,下面我们一步一步来看看数据模板如何做到化腐朽为神奇的!

一些前置条件

  • 假设你已了解了MVVM设计模式

  • 假设你已了解了一些数据绑定知识

  • 假设你已了解了一些样式知识

代码准备

  1. 首先准备一个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
    }</code></pre></li>
  2. 在准备好ViewModel,代码如下:

    public class MainViewModel: BindableBase
        {
            private IEnumerable<Employee> _employees;
        public IEnumerable&lt;Employee&gt; Employees
        {
            get =&gt; _employees;
            set =&gt; SetProperty(ref _employees, value);
        }
    
        public MainViewModel()
        {
            Employees = new List&lt;Employee&gt;()
            {
                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"},
            };
        }
    
    }</code></pre></li>

没有数据模板

准备好没有使用数据模板的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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器