控件模板基础
需求
需求:客户对目前的控件样式不满意,需要修改样式。
每一个控件都有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 绘制,不可以模板开发