关于ControlTemplate 2
(参考自 ding.li)
WPF中有三大模板ControlTemplate,DataTemplate,ItemsPanelTemplate。
ControlTemplate和ItemsPanelTemplate是控件模板(用来描述控件本身的样式)
ControlTemplate(DataTemplate是数据模板(描述控件内部数据的样式)
ControlTemplate:控件模板主要有两个重要属性:VisualTree内容属性和Triggers触发器。所谓VisualTree(视觉树),就是呈现我们所画的控件。Triggers可以对我们的视觉树上的元素进行一些变化。一般用于单内容控件。、
- 定义模板(在任何UserControl或者Resource下):
<Style TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Ellipse Width="100" Height="100"> <Ellipse.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0" Color="blue"/> <GradientStop Offset="1" Color="LightBlue"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> <Ellipse Width="80" Height="80"> <Ellipse.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="1" Color="Transparent"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
- 在MainWindows下call 模板
1 <Button Content="Hello WPF"/>
ControlTemplate之子 ContentControl和ContentPresenter
我们在ControlTemplate中画了两个椭圆,应用于所有的Button按钮(因为没有加x:key给模板),但我们Button中有Content属性(内容为 Hello WPF),却没有显示出来。因为这里用ControlTemplate重写了Button的样式,所以我们也要在ControlTemplate中增加 ContentControl。通过ContentControl中的Content来绑定父容器的Content属性。
- 为ContentControl属性赋值
1 <Style TargetType="Button"> 2 <Setter Property="Template"> 3 <Setter.Value> 4 <ControlTemplate TargetType="Button"> 5 <Grid> 6 <Ellipse Width="100" Height="100"> 7 <Ellipse.Fill> 8 <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 9 <GradientStop Offset="0" Color="blue"/> 10 <GradientStop Offset="1" Color="LightBlue"/> 11 </LinearGradientBrush> 12 </Ellipse.Fill> 13 </Ellipse> 14 <Ellipse Width="80" Height="80"> 15 <Ellipse.Fill> 16 <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 17 <GradientStop Offset="0" Color="White"/> 18 <GradientStop Offset="1" Color="Transparent"/> 19 </LinearGradientBrush> 20 </Ellipse.Fill> 21 </Ellipse> 22 <ContentControl VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"/> 23 </Grid> 24 </ControlTemplate> 25 </Setter.Value> 26 </Setter> 27 </Style>
我们来看一下,ContentControl继承于Control的,用MSDN的话是:表示包含单项内容的控件、ContentControl 可以包含任何类型的公共语言运行库对象。如下ContentControl类图。
为了提高性能,我们可以用一个ControlPresenter来代替ContentControl,效果还是一样,那他们有什么区别呢?
来看下ControlPresenter这个类,它继承于FreameworkElement,如下图:
ControlPresenter 通常叫做内容占位符。所以我们可以看到
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>来代替<ContentControl VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"/> 。这里少了Content绑定父容器,因为ControlPresenter有个隐式的Content="{TemplateBinding Content}"。
从他们的基类可以看出,ContentControl比ContentPresenter大多了。
其实ControlPresenter是一个原始的构建块,而ContentControl是一个带控件模板的成熟控件(里面包含ControlPresenter)。
一般用ControlPresenter。
ControlTemplate的VisualTree我们讲过了,下面看下他的trigger如何运用。
我们在原来的代码中增加IsMouseOver事件
<ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="ellipse1" Property="Fill" Value="Red"/> </Trigger> </ControlTemplate.Triggers>
当我们把鼠标移上去的时候就会变成如下图所示:
发挥我们的想象力,我们可以根据ControlTemplate做更多的特效。如下
1 <Style TargetType="CheckBox"> 2 3 <Setter Property="Template"> 4 5 <Setter.Value> 6 7 <ControlTemplate TargetType="CheckBox"> 8 9 <DockPanel> 10 11 <ContentPresenter DockPanel.Dock="Left" VerticalAlignment="Center" /> 12 13 <Grid> 14 15 <Grid.ColumnDefinitions> 16 17 <ColumnDefinition Width="30"/> 18 19 <ColumnDefinition Width="30"/> 20 21 </Grid.ColumnDefinitions> 22 23 <Rectangle Grid.Column="0" Grid.ColumnSpan="2" Fill="Gray"/> 24 25 <TextBlock x:Name="txtBox" Foreground="White" /> 26 27 </Grid> 28 29 </DockPanel> 30 31 <ControlTemplate.Triggers> 32 33 <Trigger Property="IsChecked" Value="True"> 34 35 <Setter TargetName="txtBox" Property="Grid.Column" Value="1"/> 36 37 <Setter TargetName="txtBox" Property="Text" Value="On"/> 38 39 <Setter TargetName="txtBox" Property="Background" Value="LightBlue"/> 40 41 </Trigger> 42 43 <Trigger Property="IsChecked" Value="{x:Null}"> 44 45 <Setter TargetName="txtBox" Property="Grid.Column" Value="0"/> 46 47 </Trigger> 48 49 <Trigger Property="IsChecked" Value="false"> 50 51 <Setter TargetName="txtBox" Property="Grid.Column" Value="0"/> 52 53 <Setter TargetName="txtBox" Property="Text" Value="OFF"/> 54 55 </Trigger> 56 57 </ControlTemplate.Triggers> 58 59 </ControlTemplate> 60 61 </Setter.Value> 62 63 </Setter> 64 65 </Style> 66 67 <Grid> 68 69 <CheckBox Width="100" Height="30" Content="Click Me"/> 70 71 </Grid>