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>
设计按钮,通过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>
<Button Style="{StaticResource ButtonStyle1}" Width="100" Height="40" Content="测试" Background="Gray"/>