控件模板基础
需求
需求:客户对目前的控件样式不满意,需要修改样式。
每一个控件都有Template属性,可以定制样式。
我下面以Button为例子:
<Button Content="Button" Height="30" Width="100">
<Button.Template>
<ControlTemplate>
<Border BorderBrush="Orange" BorderThickness="2" CornerRadius="10">
<TextBlock Text="Button" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
这里了利用模版修改了圆角,直接操作Button属性是没有的
当把Template单独拎出来的时候,需要指定TargetType属性,确实目标控件,和Key属性,方便调用
属性传值
利用TemplateBinding 来绑定控件中的值,如果不写TemplateBinding,只写值的话,控件中设置则是没有效果的。
<ControlTemplate x:Key="btnDemoTemplate" TargetType="Button">
<Border BorderBrush="Orange" BorderThickness="2"
Background="{TemplateBinding Background}" CornerRadius="10">
<TextBlock Text="Button" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
TemplateBinding 绑定使用的属性 默认的属性
ControlTemplate:需要指定:TargetType 否则绑定会出现问题 不存在
如果是复杂类型,需要使用ContentPresenter 占位
属性传递:用一个无关大雅的属性可以给ControlTemplate 传值
样式包含模板 但是不必须
引入ContentPresenter
如果Content是复杂类型,则不可以使用TextBlock,需要使用ContentPresenter来占位,进行显示。
<ControlTemplate x:Key="btnDemoTemplate" TargetType="Button">
<Border BorderBrush="Orange" BorderThickness="2" Background="{TemplateBinding Background}" CornerRadius="10">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
Style 和 Template
如果样式中有触发器,模版中也有触发器,优先使用模板的触发器。
<ControlTemplate x:Key="btnDemoTemplate" TargetType="Button">
<Border BorderBrush="Orange"
BorderThickness="2"
Background="{TemplateBinding Background}"
CornerRadius="10"
x:Name="border">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="Button">
<Setter Property="Template" Value="{StaticResource btnDemoTemplate}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
我鼠标放上的时候,颜色只会变绿色,不会触发Style中的触发器。
扩展:
如果说,我们想要按钮上有两个部分显示,一个是Content,另外一个要字体图标,请问怎么实现?
利用无关紧要的属性,进行值传递 例如:Tag
<ControlTemplate x:Key="btnDemoTemplate" TargetType="Button">
<Border BorderBrush="Orange"
BorderThickness="2"
Background="{TemplateBinding Background}"
CornerRadius="10"
x:Name="border">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{TemplateBinding Tag}" />
<ContentPresenter Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="Button">
<Setter Property="Template" Value="{StaticResource btnDemoTemplate}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
<!--加入A就是想要的图标-->
<Button Height="30" Background="Red" Tag="A" Width="100" Template="{StaticResource btnDemoTemplate}">
<Button.Content>
<Button Content="CeShi" />
</Button.Content>
</Button>
效果如下:
注意:TextBlock 和 Border 都是最基础的控件,基于DrawingRect 和 DrawingContext 绘制,不可以模板开发