WPF 模板(Template)

       模板(Template): WPF系统不但支持传统的Winfrom编程的用户界面和用户体验设计,更支持使用专门的设计工具Blend进行专业设计,同时还推出了以模板为核心的新一代设计理念。 在WPF中,通过引入模板(Template)微软将数据和算法的“内容”与“形式”解耦了。模板是算法数据外衣,决定了它们长什么样子。

WPF中的模板(Template)分为两大类:

  • ControlTemplate是算法内容的表现形式,一个控件怎样组织其内部结构才能更符合业务逻辑和需求。
  • DataTemplate是数据内容表现形式,决定一条数据显示成什么样子。

       Style(样式):设置控件样式,构成Style重要的两个元素是Setter和Trigger,Setter类帮助我们设置控件的静态外观风格,Trigger类则帮助我们设置控件的行为风格。

Template与Style联系和区别:如果只需对控件进行小幅度修饰(调整大小、位置、字体、颜色等)就用style,如果需要改变控件的外观和行为就用controlTemplate(形状、事件触发如鼠标停留效果等)。在实际项目中,经常把Template定义在Style中,通过Style 中的Property来设置控件的Template属性。

实例链接:https://download.csdn.net/download/lvxingzhe3/87654176

ControlTemplate

        控件模板主要有两个重要属性:VisualTree内容属性和Triggers触发器。所谓VisualTree(视觉树),就是呈现我们所画的控件。Triggers可以对我们的视觉树上的元素进行一些变化。一般用于单内容控件。如设置一个圆角Button的ControlTemplate实例如下:

<Window x:Class="WpfTemplate.ControlTemplateDemo"
        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:WpfTemplate"
        mc:Ignorable="d"
        Title="ControlTemplateDemo" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <!--设置控件样式-->
            <Style TargetType="Button" x:Key="btnStyle">
                <!--Setter设置控件静态属性-->
                <Setter Property="FontSize" Value="16"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}"  >
                            <Border x:Name="back" BorderBrush="{TemplateBinding Control.BorderBrush}" Background="LightBlue"  CornerRadius="5">
                                <!--ControlPresenter:内容占位符-->
                                <ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Border>
                            <ControlTemplate.Triggers>
                                <!--Triggers设置控件的行为风格-->
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter TargetName="back" Property="Background" Value="Orange"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <!--设置按钮圆角-->
        <Button  Content="取消" Width="100" Height="30" Style="{StaticResource btnStyle}"  />
    </Grid>
</Window>

效果如图:

Note:

  • Style设置Key值,控件引用其Key来设置自身样式;如果Style没有设置Key值,则Style作用域内所有TargetType类型控件都默认使用其样式。
  • ControlPresenter 通常叫做内容占位符,用来替换ContentControl控件。如果没有ControlPresenter ,内容控件就没有内容显示(Button上的字将不显示)。ItemsPresenter用于显示条目数据,作为条目内容占位符。

DataTemplate

        允许定制.NET对象的外观,也就是数据的外观,常用在以下3处:ContentControl的ContentTemplate属性,用于定制ContentControl内容的外观;ItemsControl的ItemTemplate属性,用于定制ItmsControl数据条目的外观;GridViewColumn的CellTemplate属性,相当于定制GridViewColumn单元格数据的外观。

1.ContentTemplate使用:

<Window x:Class="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:MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="360">
    <Window.Resources>
        <DataTemplate x:Key="template1">
            <TextBlock Text="{Binding}" FontSize="12" FontWeight="Bold" TextWrapping="Wrap"></TextBlock>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ContentControl Name="contCtrl" ContentTemplate="{StaticResource template1}" 
                        Content="This is the content of the content control."/>
    </Grid>
</Window>

2.ItemTemplate使用:

后端代码:

using System;
using System.Collections.Generic;
using System.Windows;
namespace WpfTemplate
{
    /// <summary>
    /// DataTemplateDemo.xaml 的交互逻辑
    /// </summary>
    public partial class DataTemplateDemo : Window
    {
        public List<Book> BookList { get; set; } = new List<Book>();
        public DataTemplateDemo()
        {
            InitializeComponent();
            BookList.Add(new Book() { Title = "三国演义", Author = "罗贯中",Time=DateTime.Now.AddYears(-200) });
            BookList.Add(new Book() { Title = "红楼梦", Author = "曹雪芹", Time = DateTime.Now.AddYears(-150) });
            BookList.Add(new Book() { Title = "西游记", Author = "吴承恩", Time = DateTime.Now.AddYears(-230) });
        }
    }
}

前端代码:

<Window x:Class="WpfTemplate.DataTemplateDemo"
        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:WpfTemplate"
        mc:Ignorable="d"
        Title="DataTemplateDemo" Name="win" Height="400" Width="600">
    <Window.Resources>
        <DataTemplate x:Key="MyDataTemplate">
            <StackPanel Orientation="Horizontal">
                <Border Background="Pink">
                    <TextBlock Text="{Binding Title}"/>
                </Border>
                <Button Content="{Binding Author}"  Cursor="Hand" Margin="10,0"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox Grid.Row="1" ItemsSource="{Binding BookList,ElementName=win}" ItemTemplate="{StaticResource MyDataTemplate}"/>
    </Grid>
</Window>

3.CellTemplate使用

<Window x:Class="WpfTemplate.DataTemplateDemo"
        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:WpfTemplate"
        mc:Ignorable="d"
        Title="DataTemplateDemo" Name="win" Height="400" Width="600">
    <Grid>
        <DataGrid  AutoGenerateColumns="False" ItemsSource="{Binding BookList,ElementName=win}" Grid.Row="1" Grid.Column="1">
            <DataGrid.Columns>
                <DataGridTextColumn Header="书名" Binding="{Binding Title}" />
                <DataGridTextColumn Header="作者" Binding="{Binding Author}" />
                <DataGridTemplateColumn Header="时间">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DatePicker SelectedDate="{Binding Time}"  BorderThickness="0" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

ItemsPanelTemplate使用: 
        ItemsPanelTemplate可以被设置为ItemsControl的ItemsPanel。例中,ItemsControl的条目显示默认是垂直排列,通过ItemsPanel属性修改为水平排列。

<Grid>
    <ListBox>
        <!--ItemsPanel-->
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
         <!--条目-->
        <TextBlock Text="Allan"/>
        <TextBlock Text="Kevin"/>
        <TextBlock Text="Drew"/>
        <TextBlock Text="Timothy"/>
    </ListBox>
</Grid>


Style中的Setter
        Setter,属性值的设置器,给属性赋值的时候一般都采用“属性名=属性值”的形式。Setter类的Property属性用来指明想为目标的哪个属性赋值;Setter类的Value属性则是提供的属性值。

Style中的Trigger
        Trigger,触发器,即当某些条件满足时会触发一个行为(比如某些值的变化或动画的发生等),主要类型有:

  • 事件触发型的EventTrigger
  • 数据变化触发型的Trigger/DataTrigger
  • 多条件触发型的MultiTrigger/MultiDataTrigger

        Trigger类是最基本的触发器。类似于Setter,Trigger也有Property和Value这两个属性,Property是Trigger 关注的属性名称,Value是触发条件。
        Trigger类还有一个Setters属性,此属性值是一组Setter,一旦触发条件被满足,这组Setter的“属性一值”就会被应用,触发条件不再满足后,各属性值会被还原。
一个针对CheckBox的Style,当CheckBox的IsChecked属性为true的时候前景色和字体会改变。XAML代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        Title="MainWindow" Height="185.425" Width="300">
    <Window.Resources>
        <Style TargetType="CheckBox">
            <!--Triggers不是Style的内容属性,<Style.Triggers>...</Style.Triggers>这层标签不能省略-->
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="true">
                    <!--Trigger的Setters属性是Trigger的内容属性,<Trigger.Setters.…</Trigger.Seters>这层标签可以省略-->
                    <!--<Trigger.Setters>-->
                    <Setter Property="FontSize" Value="20"/>
                    <Setter Property="Foreground" Value="Orange"/>
                    <!--</Trigger.Setters>-->
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <CheckBox Content="悄悄的我走了" Margin="5"/>
        <CheckBox Content="正如我悄悄的来" Margin="5,0"/>
        <CheckBox Content="我挥一挥衣袖" Margin="5"/>
        <CheckBox Content="不带走一片云彩" Margin="5,0"/>
    </StackPanel>
</Window>


        MultiTrigger必须多个条件同时成立时才会被触发,比Trigger多了一个Conditions属性,需要同时成立的条件就存储在这个集合中。改动上面的例子,要求同时满足CheckBox被选中且Content为“正如我悄悄的来”时才会被触发,XAML代码如下(仅Style部分):

<Style TargetType="CheckBox">           
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsChecked" Value="true"/>
                <Condition Property="Content" Value="正如我悄悄的来"/>
            </MultiTrigger.Conditions>
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="Foreground" Value="Orange"/>                    
        </MultiTrigger>
    </Style.Triggers>
</Style>

效果如下:

Template扩展:

       很多时候数据是以XML形式存储的,DataTemplate具有直接把XML数据结点当作目标对象的功能——XML数据中的元素名(标签名)可以作为DataType,元素的子结点和Attribute可以使用XPath来访问。下面的代码使用XmlDataProvider作为数据源,代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:local="clr-namespace:WpfApp"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        Title="MainWindow" Height="500" Width="333.035">
    <Window.Resources>
        <!--Data Template-->
        <DataTemplate DataType="Unit">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <Grid>
                        <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding XPath=@Price}"/>
                        <TextBlock Text="{Binding XPath=@Year}"/>
                    </Grid>
                    <TextBlock Text="{Binding XPath=@Price}" Margin="5.0"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" XPath="Units/Unit">
            <x:XData>
                <Units xmlns="">
                    <Unit Year="2001" Price="100"/>
                    <Unit Year="2001" Price="120"/>
                    <Unit Year="2001" Price="140"/>
                    <Unit Year="2001" Price="160"/>
                    <Unit Year="2001" Price="180"/>
                    <Unit Year="2001" Price="200"/>
                </Units>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
    <StackPanel>
        <ListBox ItemsSource="{Binding Source={StaticResource ds}}"/>
        <ComboBox ItemsSource="{Binding Source={StaticResource ds}}" Margin="5"/>
    </StackPanel>
</Window>

显示层级数据的模板HierarchicalDataTemplate
        XML最大的优势是可以方便地表示带有层级的数据,WPF准备了TreeView和Menultem控件用来显示层级数据,能够帮助层级控件显示层级数据的模板是HierarchicalDataTemplate。第一个例子是使用TreeView显示多层级、不同类型数据,需要为每种数据设计一个模板,有机会使每种数据类型有自己独特的外观。数据保存在项目根目录的Data.xml文件中,内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
  <Grade Name="一年级">
    <Class Name="甲班">         
      <Group Name="A组"/>
      <Group Name="B组"/>
      <Group Name="C组"/>
    </Class>
  <Class Name="乙班">
    <Group Name="A组"/>
    <Group Name="B组"/>
    <Group Name="C组"/>
  </Class>
  </Grade>
  <Grade Name="二年级">
    <Class Name="甲班">
      <Group Name="A组"/>
      <Group Name="B组"/>
      <Group Name="C组"/>
    </Class>
    <Class Name="乙班">
      <Group Name="A组"/>
      <Group Name="B组"/>
      <Group Name="C组"/>
    </Class>
  </Grade>
</Data>

程序的XAML代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
        Title="MainWindow" Height="400" Width="333.035">    
    <Window.Resources>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Grade"/>
        <!--年级模板-->
        <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
            <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
        <!--班级模板-->
        <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
            <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
        </HierarchicalDataTemplate>
        <!--小组模板-->
        <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding XPath=Student}">
            <CheckBox Content="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <TreeView Margin="5" ItemsSource="{Binding Source={StaticResource ds}}"/>
    </Grid>
</Window>

效果如下:

第二个例子是同一种数据类型的嵌套结构,这种情况下只需设计一个HierarchicalDataTemplate,它会产生自动迭代应用的效果。数据仍然存放在Data.xml文件中,数据全都是Operation类型:

<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
  <Operation Name="文件" Gesture="F">
    <Operation Name="新建" Gesture="N">
      <Operation Name="项目" Gesture="Control+P"/>
      <Operation Name="网站" Gesture="Control+W"/>
      <Operation Name="文档" Gesture="Control+D"/>
    </Operation>
    <Operation Name="保存" Gesture="S"/>
    <Operation Name="打印" Gesture="P"/>
    <Operation Name="退出" Gesture="X"/>
  </Operation>
  <Operation Name="编辑" Gesture="E">
    <Operation Name="拷贝" Gesture="Control+C"/>
    <Operation Name="剪切" Gesture="Control+X"/>
    <Operation Name="粘贴" Gesture="Control+V"/>
  </Operation>
</Data>

 程序的XAML代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="300" Width="300">
    <Window.Resources>
        <!--数据源-->
        <XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Operation"/>
        <!--Operation 模板-->
        <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
                <TextBlock Text="{Binding XPath=@Gesture}"/>
            </StackPanel>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <StackPanel MenuItem.Click="StackPanel_Click">
        <Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
    </StackPanel>
</Window>

HierarchicalDataTemplate的作用目标是Menultem的Header,可以从被单击Menultem的Header中取出XML数据。事件处理器代码如下:

private void StackPanel_Click(object sender, RoutedEventArgs e)
{
    MenuItem mi = e.OriginalSource as MenuItem; 
    XmlElement xe = mi.Header as XmlElement; 
    MessageBox.Show(xe.Attributes["Name"].Value);
}

效果如下:

 Note:可以维护一个CommandHelper类,根据拿到的数据来决定执行什么RoutedCommand。

从外界访问Template内部的控件及其属性值
        由ControlTemplate或DataTemplate生成的控件都是“由Template生成的控件”,ControlTemplate和DataTemplate两个类均派生自FrameworkTemplate类,有个名为FindName的方法可以检索其内部控件。
检索ControlTemplate生成的控件
设计一个ControlTemplate并把它应用在一个UserControl上,界面上还有一个Button,在它的Click事件处理器中检索由ControlTemplate生成的代码。
程序的XAML代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="160" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel Background="Orange">
                <TextBox x:Name="textBox1" Margin="6"/>
                <TextBox x:Name="textBox2" Margin="6,0"/>
                <TextBox x:Name="textBox3" Margin="6"/>
            </StackPanel>                  
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Background="Yellow">
        <UserControl x:Name="uc" Template="{ StaticResource cTmp}" Margin="5"/> 
        <Button Content="Find by Name" Width="120" Height="30" Click="Button_Click"/>
    </StackPanel>
</Window>

后台代码如下:

 private void Button_Click(object sender, RoutedEventArgs e)
 {
     TextBox tb = this.uc.Template.FindName("textBox1", this.uc) as TextBox;
     tb.Text = "Hello WPF";
     StackPanel sp = tb.Parent as StackPanel;
     (sp.Children[1] as TextBox).Text = "Hello ControlTemplate,I can find you!";
 }

Trigger扩展:

由数据触发的DataTrigger
基于数据执行某些判断可以考虑使用DataTrigger,DataTrigger对象的Binding属性会把数据源源不断送过来,一旦送来的值与Value属性一致DataTrigger即被触发。
下面例子中,当TextBox的Text长度小于7个字符时其Border会保持红色,XAML代码如下:
 

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow" Height="123.435" Width="204.297">
    <Window.Resources>
        <local:L2BConverter  x:Key="cvtr"/>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <DataTrigger Binding="{ Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text.Length, Converter={ StaticResource cvtr}}" Value="false">
                    <Setter Property="BorderBrush" Value="Red"/>
                    <Setter Property="BorderThickness" Value="1"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBox Margin="5"/>
        <TextBox Margin="5,0"/>
        <TextBox Margin="5"/>
    </StackPanel>
</Window>

        为了将控件自己作为数据源需要使用RelativeSource,如果不明确指出Source时Binding会把控件的DataContext属性当作数据源而非把控件自身当作数据源。
Binding的Path被设置为Text.Length,字符串的长度是一个具体的数字,基于这个长度值做判断时需要用到Converter,创建如下的Converter:

//经Converter转换后,长度值会转换成bool类型值,DataTrigger的Value被设置为false。
public class L2BConverter : IValueConverter 
{ 
    public object Convert(object value,Type targetype,object parameter, CultureInfo culture)
    {
        int textLength = (int)value; 
        return textLength > 6 ? true : false;
    }
    public object ConvertBack(object value, Type targetype, object parameter, CultureInfo culture) 
    {
        throw new NotImplementedException();
    }
}

效果如下:

多数据条件触发的MultiDataTrigger
        遇到要求多个数据条件同时满足时才能触发变化的需求,此时可以考虑使用MultiDataTrigger。
用户界面上使用ListBox显示了一列Student数据,当Student对象同时满足ID为2、Name为Tom的时候条目就高亮显示,示例的XAML代码如下:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
        Title="MainWindow" Height="123.435" Width="300">
    <Window.Resources>
        <Style TargetType="ListBoxItem">
            <!--使用Style设置DataTemplate-->
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding ID}" Width="60"/>
                            <TextBlock Text="{Binding Name}" Width="120"/>
                            <TextBlock Text="{Binding Age}" Width="60"/>                            
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
            <!--MultiDataTrigger-->
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=ID}" Value="2"/>
                        <Condition Binding="{Binding Path=Name}" Value="Tom"/>
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.Setters>
                        <Setter Property="Background" Value="Orange"/>
                    </MultiDataTrigger.Setters>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>        
    </Window.Resources>
    <StackPanel>
        <ListBox x:Name="listBoxStudent" Margin="5"/>
    </StackPanel>
</Window>

后台代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        List<Student> studentList = new List<Student>() 
        {new Student(){ ID=1, Name="Tim", Age=21},
        new Student(){ ID=2, Name="Tom", Age=22 }}; 
        
        this.listBoxStudent.ItemsSource = studentList;
    } 
}
public class Student
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

效果如下:

由事件触发的EventTrigger
EventTrigger是触发器中最特殊的一个,它是由事件来触发,被触发后执行一段动画,U1层的动画效果往往与EventTrigger相关联。
创建了一个针对Button的Style,这个Style包含两个EventTrigger,一个由MouseEnter事件触发,另一个由MouseLeave事件触发。XAML代码如下:

        <!--由事件触发的EventTrigger-->
        <Style TargetType="Button">
            <Style.Triggers>
                <!--鼠标进入-->
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Width"/>
                            <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Height"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <!--鼠标离开-->
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width"/>
                            <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>

效果如下:

   

 参考:WPF之模板_51CTO博客_wpf 模板

  实例链接:https://download.csdn.net/download/lvxingzhe3/87654176

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: WPF(Windows Presentation Foundation)是一种用于构建Windows应用程序的技术,而UI template是一种在WPF中用于创建可重复使用的用户界面样式和布局的机制。 WPF的UI template可以理解为一种定义了界面元素外观和样式的模板。通过使用UI template,我们可以很方便地将相同的界面元素样式应用于多个控件,从而实现界面的一致性和可重用性。 使用UI template的好处之一是简化了界面开发工作。开发人员只需要定义一次UI模板,然后可以在需要的地方直接应用这个模板,而不需要重新编写和调整样式。这在多个界面元素需要拥有相同外观的情况下特别有用。 另一个好处是提高了界面的灵活性。通过修改UI template,我们可以轻松地调整控件的样式、布局和属性,而不会破坏应用程序的整体结构。这样可以节省大量的时间和工作量,并且可以使界面更容易维护。 在WPF中,UI template是由XAML语言定义的。通过使用XAML,开发人员可以以声明式的方式定义界面元素的外观和样式,而不需要编写繁琐的代码。这使得UI template的创建、修改和管理变得更加方便和直观。 总的来说,WPF的UI template是一种用于创建可重复使用的用户界面样式和布局的机制,它可以简化界面开发工作,提高界面的灵活性,并通过XAML语言实现了对界面的声明式定义。 ### 回答2: WPF(Windows Presentation Foundation)是微软推出的一种用于构建富客户端应用程序的技术。在WPF中,UI模板(UI Template)是一种定义了控件外观和行为的重要组成部分。 UI模板被用于定义控件在界面上的外观,比如控件的背景、边框、字体样式、布局等。通过使用UI模板,我们可以根据应用程序的需求,自定义控件的外观,使之符合我们期望的样式和风格。这种灵活性使得WPF应用程序可以呈现出各种独特的界面设计。 UI模板的创建主要分为两个步骤:定义模板和应用模板。首先,我们需要根据需要定义一个模板,可以使用XAML(eXtensible Application Markup Language)来描述模板的结构和样式。模板中可以包含多个可视元素和控件,并可以使用各种布局控件进行排列。其次,我们需要将定义好的模板应用到相应的控件上。在WPF中,通过将控件的Template属性设置为我们定义的模板,就可以使控件采用我们自定义的样式。 使用UI模板可以为应用程序带来很多好处。首先,它使得应用程序的界面设计能够与众不同,使其与其他应用程序区别开来,提供独特的用户体验。其次,UI模板的灵活性使得我们可以方便地修改和调整控件的外观,而无需改变控件的内部逻辑。这种分离了界面与逻辑的设计思想有助于增强应用程序的可维护性和可扩展性。 总之,WPF的UI模板是一种非常强大的工具,可以帮助开发者定制出各种独特且具有个性化的界面,从而提升应用程序的用户体验。 ### 回答3: WPF (Windows Presentation Foundation)是一种用于创建丰富而功能强大的Windows桌面应用程序的框架。在WPF中,UI模板是一种用于定义UI元素外观和行为的技术。 UI模板是一种XAML标记语言的结构,它描述了如何渲染和布局一个UI元素,从而决定了它的外观和行为。UI模板可以用于自定义各种控件,例如按钮、文本框、列表和窗体等。通过创建和应用UI模板,开发者可以完全控制和定制应用程序的外观和交互方式。 WPF的UI模板由多个元素组成,其中包括容器元素、面板元素、控件元素和视觉元素等。容器元素用于包含和布局其他元素,面板元素用于定义元素的排列方式,控件元素用于添加交互和功能,视觉元素用于定义元素的外观。 开发者可以使用Visual Studio等工具创建和编辑UI模板。在模板中,可以通过修改元素的属性、样式和模板绑定来改变元素的外观和行为。还可以通过添加触发器和动画等功能来实现交互效果。 通过使用UI模板,开发者可以根据自己的需求和设计要求来定制应用程序的外观。他们可以创建独特和个性化的用户界面,从而提供更好的用户体验。此外,UI模板还可以被多个控件共享,以实现统一的外观和风格。 总之,WPF的UI模板是一种强大的工具,可以让开发者自由定制和控制应用程序的外观和行为。通过使用UI模板,可以创建独特和个性化的用户界面,为用户提供更好的体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无熵~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值