WPF学习之--DataTemplate、ControlTemplate和Style的应用

概览

控件只是数据和行为的载体,是个抽象的概念,至于它本身长成什么样子(控件内部结构),它的数据会长成什么样子(数据显示结构)都是靠Template生成的。

 

DataTemplate和ControlTemplate的联系和区别

DataTemplate控件树是ControlTemplate里面的一棵子树。 

决定【控件外观和行为的是ControlTemplate使用TemplateBinding来绑定源对象的属性,例如{TemplateBinding Background} 】;

决定数据外观的是【DataTemplate,使用Binding来绑定数据对象的属性,例如{Binding PersonName}】,它的载体是ContentPresenter对象。

 

 Control类

  -Template属性(controlTemplate类型)

    -ContentPresenter

      -ContentTemplate(DataTemplate类型)

 

 

总结ControlTemplate和DataTemplate的关系:

ControlTemplate内有一个ContentPresenter属性,这个ContentPresenter的ContentTemplate就是DataTemplate类型


 

以下介绍用法

 在Template中设置ControlTemplate 和 DataTemplate的应用有2种方法,一种是逐个设置控件自身的Template/【ContentTemplate/ItemsTemplate/CellTemplate】;另一种是通过Style来应用,如以下所示。

<Style x:Key="carDetailViewTemplate" TargetType="{x:Type UserControl}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate >
          ......
          </DataTemplate >
</Setter.Value> </Setter Property="ContentTemplate"> </Style>


<style TargetType="{x:Type TextBox}">
  <Setter property="Template">
    <Setter.Value>
      <ControlTemplate>

      </ControlTemplate>
    </Setter.Value>
  </Setter>
</style>

 

一、ControlTemplate

 可以借助Style来实现,也可以不用,它包含2个重要属性:VisualTree【使用这个属性来描述控件外观】和Triggers【定制反应】

/*资源词典*/  /*整体应用*/
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp1.XmlResource">
    <Style  x:Key="Sample1" TargetType="{x:Type TextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Border x:Name="Bd" SnapsToDevicePixels="True"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="5">
                        <ScrollViewer x:Name="PART_ContentHost"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>    
</ResourceDictionary>

/*如何引用上述资源*/
<Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="XmlResource\Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
</Window.Resources>
<Grid>
        <TextBox  Style="{StaticResource Sample1}"/>
</Grid>

 ControlTemplate里的控件可以使用TemplateBinding将自己的属性值关联在目标控件的某个属性值上,必要的时候还可以添加Converter。

 

二、DataTemplate

数据内容的表现形式,是数据的外衣。常用在三处:ContentTemplate,ItemTemplate和CellTemplate

ContentControl族包含的控件

Button CheckBox ComboBoxItem Label
ListBoxItem ListViewItem RadioButton ScrollView
UserControl Window ToolTip ButtonBase
       

 DataTemplate控件树是ControlTemplate控件树的一颗子树。

<DataTemplate>
  <Grid>
    <StackPanel Orientation="Horizontal">
    <Grid>
      <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding Price}"/>
      <TextBlock Text="{Binding Year}"/>
    </Grid>
      <TextBlock Text="{Binding Price}"/>
    </StackPanel>
  </Grid>
</DataTemplate>

 TemplateBinding和Binding的区别

(1)最重要的区别TemplateBinding仅支持单向的数据绑定。

(2)Binding比TemplateBinding更加灵活,但是开销大。TemplateBinding的功能和{Binding RelativeSource={RelativeSource TemplatedParent}}一致。

三、Style的介绍

Style用来给控件设计多种外观样式和行为样式,只能改变控件已有的属性。

主要由Setter(设置器)和Trigger(触发器)两种元素组成。Setter帮助我们设置控件的静态外观,Trigger(触发器,满足条件时触发一个行为)帮助我们设置控件的行为风格。

1. Setter的使用

 

<Window.Resource>
    <Style TargetType="TextBlock">
        <Setter Property="FontSize" value="24"/>
    </Style>
</Window>

设置控件的ControlTemplate,把Setter的Property设置为Template 并给Value提供一个ControlTemplate。

<Window.Resources>


<Style x:Key="IsMouseOver">
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="true">
<!-- 当鼠标移过按钮时,触发样式变更-->
<Setter Property="Control.FontStyle" Value="Italic"/>
<Setter Property="Control.Background" Value="Blue"/>
<Setter Property="Control.FontSize" Value="18"/>
</Trigger>
</Style.Triggers>
</Style>

<Style x:Key="ButtonStyleLogin" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Image x:Name="minBtn" Source="Point1.png" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="Point2.png" TargetName="minBtn" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Source" Value="Point3.png" TargetName="minBtn" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="137,201,0,0" VerticalAlignment="Top" Width="218" Height="58" Style="{StaticResource ButtonStyleLogin}"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="515,201,0,0" VerticalAlignment="Top" Width="175" Height="58" Style="{StaticResource IsMouseOver}"/>
</Grid>



2.Trigger的使用

(1)基本Trigger

由Property(关注的属性名称) Value(触发条件)和Setters(一组Setter)三个属性组成

 <Style x:Key="CheckBoxStyle" TargetType="CheckBox">
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Trigger.Setters>
                        <Setter Property="FontSize" Value="20"/>
                        <Setter Property="Foreground" Value="Orange"/>
                    </Trigger.Setters>
                </Trigger>
            </Style.Triggers>
        </Style>

<CheckBox Content="CheckBox" HorizontalAlignment="Left" Margin="235,293,0,0" VerticalAlignment="Top" Height="23" Width="86" Style="{StaticResource CheckBoxStyle}"/>

 

(2)MultiTrigger:多条件同时成立才会被触发,比Trigger多了一个Condition属性

<Style x:Key="CheckBoxStyle" TargetType="CheckBox">
            <Style.Triggers>
               

                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsChecked" Value="true"/>
                        <Condition Property="Content" Value="yxz"/>
                    </MultiTrigger.Conditions>
                    <MultiTrigger.Setters>
                        <Setter Property="FontSize" Value="20"/>
                        <Setter Property="Foreground" Value="Red"/>
                    </MultiTrigger.Setters>
                </MultiTrigger>
            </Style.Triggers>
        </Style>

 

 

(3)DataTrigger

 

(4)MultiDataTrigger多数据条件触发器

 

(5)EventTrigger

由事件触发,执行的是一段动画,UI层的动画效果一般和它有关。

 <Style TargetType="Button" x:Key="ButtonStyle">
            <Style.Triggers>
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation To="15" Duration="0:0:0:2" Storyboard.TargetProperty="Width"/>
                            <DoubleAnimation To="15" 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>

 

总结:

1.触发器不仅仅存在与Style中,各种Template也拥有自己的触发器。

2.控件模板与Style的异同,都是为了实现空间的个性化。但Style只能改变控件已有的属性(比如字体颜色等),二控件模板可以改变空间的内部结构(视觉树)来完成更为复杂的定制。

 应用实例:

设计按钮,通过按钮自身的Template来设计

 <Button Width="50" Height="50" Background="Red" Content="测试"> 
                <Button.Template>
                    <ControlTemplate>
                        <Grid>
                            <Ellipse x:Name="ellipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Button.Height}" Fill="{TemplateBinding Button.Background}"/>
                            <ContentPresenter x:Name="contP" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Button.Content}"/>
                            
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Button.IsPressed" Value="True">
                                <Setter Property="Ellipse.Fill" Value="LightBlue" TargetName="ellipse"/>
                                <Setter Property="Button.FontSize" Value="20" TargetName="contP"/>
                            </Trigger>
                            
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Button.Template>
            </Button>
View Code

 

设计按钮,通过Style来设计

 <Style x:Key="ButtonStyle1" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            <Border x:Name="border" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Button.Height}" Background="{TemplateBinding Button.Background}"/>
                            <ContentPresenter x:Name="contP" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Button.Content}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Button.IsPressed" Value="True">
                                <Setter Property="Border.Background" Value="Blue" TargetName="border"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                   
                </Setter.Value>
            </Setter>
        </Style>
View Code
 <Button Style="{StaticResource ButtonStyle1}" Width="100" Height="40" Content="测试" Background="Gray"/>

 

posted @ 2021-08-24 00:02  HelloWorld庄先生  阅读(2630)  评论(1编辑  收藏  举报