Control Templates 控制模板
简单控制模板
<Button Margin="0,0,2,2" Grid.Row="0" Grid.Column="0" Name="cell00" >
<Button.Template>
<ControlTemplate>
<Grid>
<Rectangle Fill="Orange"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
控件模板和样式

<Style TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="32pt"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Fill="Green" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Template Binding 模板绑定
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Setter Property="FontSize" Value="32pt"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Fill="{TemplateBinding Property=Background}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
模板绑定类似于数据绑定,只是要绑定的属性来自您要替换其模板的控件(称为templatedparent)在我们的例子中, Button类的任何依赖属性都可以作为模板绑定源
完整绑定提供的扩展选项,可以在模板内使用Binding对象,其RelativeSource为TemplatedParent以指示如何解析路径
<Rectangle Fill="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}}" />
将控件模板与样式完全分离到一个单独的资源中:
<ControlTemplate x:Key="ButtonTemplate">
<Grid>
<Rectangle Fill="{TemplateBinding Property=Button.Background}"/>
</Grid>
</ControlTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="FontSize" Value="32pt"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
</Style>
与样式一样,我们可以通过在ControlTemplate元素上设置TargetType属性来避免在模板绑定属性名称前加上类前缀:
<ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}"/>
</Grid>
</ControlTemplate>
Content Presenters 内容展示器
内容展示器是 WPF 等同于“您的内容”,它允许在运行时插入由ContentControl持有的内容。
<ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
<Border Background="{TemplateBinding Property=Background}">
<!--<ContentPresenter Content="{TemplateBinding Property=Content}"/>-->
<!--设置了TargetType属性,可以简化-->
<ContentPresenter Margin="{TemplateBinding Property=Padding}"/>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Padding" Value="20"/>
</Style>
将Padding从按钮内部映射到内容呈现器 Margin外部
就像Padding和Margin之间的映射一样,构建为您提供所需外观的元素并从模板化父级绑定适当
的属性将是创建您自己的控件模板的大量工作。
Template Triggers 模板触发器
<ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}"
Name="rect" />
<ContentPresenter Margin="{TemplateBinding Property=Padding}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rect" Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Blue" GlowSize="10" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Repurposing an existing property 扩展模板
在构建控件模板时,通常情况下您想要公开的变量多于被“模板化”的控件上的属性
<ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}"
Name="rect" />
<ContentPresenter Margin="{TemplateBinding Property=Padding}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rect" Property="BitmapEffect"
Value="{Binding Path=Tag,RelativeSource={RelativeSource TemplatedParent}}">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
<Setter Property="Tag">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Yellow" GlowSize="10"/>
</Setter.Value>
</Setter>
</Style>
当IsMouseOver属性为True时,控件模板的触发器使用Tag属性的值。请注意,我们使用普通绑定(使用TemplatedParent RelativeSource)而不是模板绑定,因为普通绑定对象在运行时支持强制转
换,而模板绑定在编译时静态检查类型。正常绑定的使用使我们能够从对象类型的Tag属性中拉出BitmapEffect 。
当我们使用这种样式创建一个按钮时, Tag值充当默认值,我们可以用任何满足我们想象的位图效果来覆盖它(如示例 9‑6 中的中间按钮所示)。
<Button Margin="0,0,2,2" Grid.Row="0" Grid.Column="0" Name="cell00" >
<Button.Tag>
<BevelBitmapEffect BevelWidth="10"/>
</Button.Tag>
</Button>
请记住,控件的工作是提供行为。控件模板提供视觉效果。控件可以提供一组默认的视觉效果,但它应该允许替换这些视觉效果,以便提供与内置控件相同的灵活性。如果您需要同时提供自定义行为
和自定义视觉效果,请构建两个组件:一个控件和一个设计用于合并到控件模板中的元素。符合这种
当然,控件不可能完全独立于其视觉效果。如果控件要正确运行,任何控件都会强加一些模板必须满足的要求。这些要求的范围因控制而异。
任何控件类型与样式或模板之间都存在隐含的契约。
控件允许通过替换可视化树来自定义其外观,但树必须反过来代表控件提供某些功能。
以下部分描述了控件与其模板相关的各种方式。
浙公网安备 33010602011771号