WPF之淺談數(shù)據(jù)模板(DataTemplate)

數(shù)據(jù)模板有什么用

簡而言之,數(shù)據(jù)模板能讓你更方便、更靈活的顯示你的各類數(shù)據(jù)。只有你想不到,沒有它做不到的(感覺有點(diǎn)夸張,實(shí)踐之后,你就覺得一點(diǎn)不夸張 :sunglasses:)。

直接對比下效果:

無數(shù)據(jù)模板

2023-06-04-09-28-41-image.png

應(yīng)用了數(shù)據(jù)模板

2023-06-04-09-39-27-image.png

好了,下面我們一步一步來看看數(shù)據(jù)模板如何做到化腐朽為神奇的!

一些前置條件

  • 假設(shè)你已了解了MVVM設(shè)計(jì)模式

  • 假設(shè)你已了解了一些數(shù)據(jù)綁定知識

  • 假設(shè)你已了解了一些樣式知識

代碼準(zhǔn)備

  1. 首先準(zhǔn)備一個(gè)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
        }
    
  2. 在準(zhǔn)備好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="技術(shù)售后部",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="研發(fā)部",Job="高級軟件工程師",Sex=Sex.Male,Email="Wang.Xiaowei@wpf.com"},
                };
            }
    
        }
    

沒有數(shù)據(jù)模板

準(zhǔn)備好沒有使用數(shù)據(jù)模板的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>

運(yùn)行下程序,就會出現(xiàn)這樣的界面

2023-06-04-09-28-41-image.png

熟悉.Net的同學(xué),應(yīng)該看出來每一項(xiàng)顯示的是對象的ToString方法返回的值。因?yàn)槲覀兗现写娣诺氖菑?fù)雜類型的對象,如果沒有數(shù)據(jù)模板,ListBox默認(rèn)就會用ToString去顯示。而ToString方法默認(rèn)返回的就是對象的類型限定名。

既然了解到這個(gè)原理,那我們重載實(shí)現(xiàn)下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}";
        }
    }

再次運(yùn)行程序,結(jié)果如下

2023-06-14-20-02-03-image.png

這次算是顯示出一些有用信息了,但這樣的UI體驗(yàn),未免太差。如何讓我們的數(shù)據(jù)呈現(xiàn)更加吸引人呢?下面就輪到數(shù)據(jù)模板大顯身手了。

應(yīng)用數(shù)據(jù)模板

直接上應(yīng)用了數(shù)據(jù)模板的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>

其實(shí)數(shù)據(jù)模板就是把對象的屬性綁定到不同的UI控件上,然后通過合理的布局,就能顯示讓數(shù)據(jù)顯示的更加美觀了。

2023-06-14-20-07-27-image.png

怎么樣?效果完全就不一樣了,到這里,相信同學(xué)你應(yīng)該能get到數(shù)據(jù)模板的作用了!當(dāng)然這個(gè)只是數(shù)據(jù)模板的最基本用法,其實(shí)數(shù)據(jù)模板還有其他更強(qiáng)大的功能。比如可以通過數(shù)據(jù)模板讓男性員工的名字顯示成淡藍(lán)色,女性的名字顯示成淡綠色。這個(gè)功能下面觸發(fā)器的部分會介紹。

我們還是接著數(shù)據(jù)模板定義這部分內(nèi)容,我們是通過重寫了ListBox.ItemTemplate來定義數(shù)據(jù)模板的,但如果在其他控件我們也要顯示這樣,豈不是在定義一遍這個(gè)數(shù)據(jù)模板?這樣明顯不符合我們代碼復(fù)用的原則。還好,在wpf中,我們可以通過資源的方式來定義通用的數(shù)據(jù)模板,代碼如下

<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>

此時(shí)我們發(fā)現(xiàn),并不需要重新定義ListBox.ItemTemplate,但運(yùn)行結(jié)果和上面保持一致!

數(shù)據(jù)觸發(fā)器

前面我們提到可以通過數(shù)據(jù)模板讓男性員工的名字顯示成淡藍(lán)色,女性的名字顯示成淡綠色,其實(shí)就可以通過數(shù)據(jù)觸發(fā)器來實(shí)現(xiàn)這樣的功能。

這里簡單說下觸發(fā)器的作用,更詳細(xì)的去看[微軟的官方文檔](DataTrigger Class (System.Windows) | Microsoft Learn)。觸發(fā)器就是當(dāng)綁定的數(shù)據(jù)滿足某個(gè)條件時(shí),可以去設(shè)置一些控件的屬性值,或者執(zhí)行一些動作(例如動畫)。

基于觸發(fā)器原理,實(shí)現(xiàn)的代碼如下

<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>

運(yùn)行結(jié)果


2023-06-14-20-35-20-image.png

我們可以看到是通過修改顯示名字的TextBlock的字體顏色來實(shí)現(xiàn)我們需求的,其實(shí)我們可以同時(shí)設(shè)置多個(gè)控件的屬性來滿足更復(fù)雜的需求的。

到這里,淺談數(shù)據(jù)模板就接近尾聲了,所謂淺談,其實(shí)把數(shù)據(jù)模板的核心用法都覆蓋到了,在實(shí)際項(xiàng)目開發(fā)中,都是基于這些知識的靈活應(yīng)用!

最后

奉上源代碼 https://gitee.com/liuww06/wpfpractice/tree/master/src/WpfPractice.DataTemplateDemo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容