Wpf 简明教程

WPF - Templates

模板描述控件的整体外观和视觉效果。对于每个控件,都有一个与其关联的默认模板,它赋予控件外观。在 WPF 应用程序中,当你希望自定义控件的视觉行为和视觉外观时,可以轻松创建你自己的模板。

可以通过数据绑定来实现逻辑和模板之间的连接。 stylestemplates 之间的主要区别如下 -

  1. 样式只能使用该控件的默认属性来更改控件的外观。

  2. 使用模板,你可以访问控件比样式中更多的部分。你还可以指定控件的现有和新行为。

最常用的两种模板类型 −

  1. Control Template

  2. Data Template

Control Template

控件模板定义控件的视觉外观。所有 UI 元素既具有一定的外观又有行为,例如,按钮具有外观和行为。单击事件或鼠标悬停事件是响应单击和悬停而触发的行为,另外按钮还具有一定的默认外观,可以通过控件模板更改。

Example

我们来看个简单的示例。我们将创建两个按钮(一个带模板,另一个是默认按钮),并用一些属性初始化它们。

<Window x:Class = "TemplateDemo.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Window.Resources>
      <ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button">

         <Grid>
            <Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" >
               <Ellipse.Fill>
                  <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4">
                     <GradientStop Offset = "0" Color = "Red" />
                     <GradientStop Offset = "1" Color = "Orange" />
                  </LinearGradientBrush>
               </Ellipse.Fill>
            </Ellipse>

            <ContentPresenter Content = "{TemplateBinding Content}"
               HorizontalAlignment = "Center" VerticalAlignment = "Center" />
         </Grid>

         <ControlTemplate.Triggers>

            <Trigger Property = "IsMouseOver" Value = "True">
               <Setter TargetName = "ButtonEllipse" Property = "Fill" >
                  <Setter.Value>
                     <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4">
                        <GradientStop Offset = "0" Color = "YellowGreen" />
                        <GradientStop Offset = "1" Color = "Gold" />
                     </LinearGradientBrush>
                  </Setter.Value>
               </Setter>
            </Trigger>

            <Trigger Property = "IsPressed" Value = "True">
               <Setter Property = "RenderTransform">
                  <Setter.Value>
                     <ScaleTransform ScaleX = "0.8" ScaleY = "0.8"
                        CenterX = "0" CenterY = "0"  />
                  </Setter.Value>
               </Setter>
               <Setter Property = "RenderTransformOrigin" Value = "0.5,0.5" />
            </Trigger>

         </ControlTemplate.Triggers>

      </ControlTemplate>
   </Window.Resources>

   <StackPanel>
      <Button Content = "Round Button!"
         Template = "{StaticResource ButtonTemplate}"
         Width = "150" Margin = "50" />
      <Button Content = "Default Button!" Height = "40"
         Width = "150" Margin = "5" />
   </StackPanel>

</Window>

当你编译并执行以上代码时,将会显示以下 MainWindow。

control template

当你将鼠标移动至带有自定义模板的按钮上时,该按钮的颜色会发生变化,如下所示。

mouse over with control template

Data Template

数据模板定义并指定数据集合的外观和结构。它提供了格式化和定义在任何 UI 元素中演示数据的功能。它主要用于与数据相关的项目控件,例如 ComboBox、ListBox 等等。

Example

  1. 我们通过一个简单的示例来了解数据模板的概念。创建一个名为 WPFDataTemplates 的新 WPF 项目。

  2. 在以下 XAML 代码中,我们将创建一个数据模板作为资源,来保存标签和文本框。这里还有一个按钮和一个列表框,用于显示数据。

<Window x:Class = "WPFDataTemplates.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:WPFDataTemplates"
   xmlns:loc = "clr-namespace:WPFDataTemplates"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <Window.Resources>
      <DataTemplate DataType = "{x:Type loc:Person}">

         <Grid>
            <Grid.RowDefinitions>
               <RowDefinition Height = "Auto" />
               <RowDefinition Height = "Auto" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
               <ColumnDefinition Width = "Auto" />
               <ColumnDefinition Width = "200" />
            </Grid.ColumnDefinitions>

            <Label Name = "nameLabel" Margin = "10"/>
            <TextBox Name = "nameText" Grid.Column = "1" Margin = "10"
               Text = "{Binding Name}"/>
            <Label Name = "ageLabel" Margin = "10" Grid.Row = "1"/>
            <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "10"
               Text = "{Binding Age}"/>
         </Grid>

      </DataTemplate>
   </Window.Resources>

   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height = "Auto" />
         <RowDefinition Height = "*" />
      </Grid.RowDefinitions>

      <ListBox ItemsSource = "{Binding}" />
      <StackPanel Grid.Row = "1" >
         <Button Content = "_Show..." Click = "Button_Click" Width = "80" HorizontalAlignment = "Left" Margin = "10"/>
      </StackPanel>

   </Grid>

</Window>

这是 implementation in C# ,其中将一个 Person 对象列表分配给了 DataContext,包括 Person 类实现和按钮单击事件。

using System.Collections.Generic;
using System.Windows;

namespace WPFDataTemplates {

   public partial class MainWindow : Window {

      Person src = new Person { Name = "Ali", Age = 27 };
      List<Person> people = new List<Person>();

      public MainWindow() {
         InitializeComponent();
         people.Add(src);
         people.Add(new Person { Name = "Mike", Age = 62 });
         people.Add(new Person { Name = "Brian", Age = 12 });
         this.DataContext = people;
      }

      private void Button_Click(object sender, RoutedEventArgs e) {
         string message = src.Name + " is " + src.Age;
         MessageBox.Show(message);
      }
   }

   public class Person {
      private string nameValue;

      public string Name {
         get { return nameValue; }
         set { nameValue = value; }
      }

      private double ageValue;

      public double Age {
         get { return ageValue; }
         set {
            if (value != ageValue) {
            ageValue = value;
            }
         }
      }
   }

}

当你编译并执行以上代码时,将生成以下窗口。它包含一个列表,在列表框中,每个列表框项目都包含 Person 类的对象数据,这些数据显示在标签和文本框上。

data template