学海无涯

导航

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>

 请记住,控件的工作是提供行为。控件模板提供视觉效果。控件可以提供一组默认的视觉效果,但它应该允许替换这些视觉效果,以便提供与内置控件相同的灵活性。如果您需要同时提供自定义行为

和自定义视觉效果,请构建两个组件:一个控件和一个设计用于合并到控件模板中的元素。符合这种 
当然,控件不可能完全独立于其视觉效果。如果控件要正确运行,任何控件都会强加一些模板必须满足的要求。这些要求的范围因控制而异。
任何控件类型与样式或模板之间都存在隐含的契约。
控件允许通过替换可视化树来自定义其外观,但树必须反过来代表控件提供某些功能。
 
以下部分描述了控件与其模板相关的各种方式。
 
 
 
 
 

 

posted on 2023-01-13 18:21  宁静致远.  阅读(45)  评论(0编辑  收藏  举报