样式和ControlTemplate之间的区别


69

您能否告诉我Style和ControlTemplate之间的主要区别是什么?什么时候或为什么要使用其中一个?

在我看来,它们是完全一样的。作为初学者,我认为我是错的,因此是我的问题。



3
MSDN资源,样式和模板之间的区别:msdn.microsoft.com/en-us/library/…–
Stephane Rolland

Answers:


14

您可以将样式视为将一组属性值应用于多个元素的便捷方法。您可以通过直接在每个TextBlock元素上设置属性(例如FontSize和FontFamily)来更改默认外观。但是,如果希望TextBlock元素共享某些属性,则可以在XAML文件的“资源”部分中创建一个样式。

另一方面,ControlTemplate指定控件的视觉结构和视觉行为。您可以通过给控件一个新的ControlTemplate来自定义控件的外观。创建ControlTemplate时,可以替换现有控件的外观而不更改其功能。例如,您可以使应用程序中的按钮变为圆形而不是默认的正方形,但是该按钮仍会引发Click事件。

参考:http : //msdn.microsoft.com/en-us/library/ms745683.aspx


79

在样式中,您可以设置控件的属性。

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Red"/>
</Style>

<Button Style="{StaticResource MyButtonStyle}"/>

所有使用此样式的按钮都将其背景设置为红色。

在模板中,定义控件的UI(结构)。

<ControlTemplate x:Key="MyButtonTemplate" TargetType="Button">
    <Grid>
        <Rectangle Fill="Green"/>
        <ContentPresenter/>
    </Grid>
</ControlTemplate>

<Button Template="{StaticResource MyButtonTemplate}"/>

使用此模板的所有按钮将具有绿色背景,无法更改。

模板中设置的值只能通过替换整个模板来替换。在使用控件时,可以通过显式设置值来替换样式中的值。这就是为什么最好通过使用TemplateBinding而不是编码值来使用控件的属性。

<ControlTemplate x:Key="MyButtonTemplate" TargetType="Button">
    <Grid>
        <Rectangle Fill="{TemplateBinding Background}"/>
        <ContentPresenter/>
    </Grid>
</ControlTemplate>

现在,该模板使用了应用于该按钮的Background属性的值,因此可以对其进行自定义:

<Button Template="{StaticResource MyButtonTemplate}" Background="Yellow"/>

另一个有用的功能是控件可以选择默认样式,而无需为它们分配特定的样式。您无法使用模板来做到这一点。

只需删除样式的x:Key属性即可(同样:您无法使用模板执行此操作)。样式下方视觉树中的所有按钮都将应用此样式。

组合模板和样式非常强大:您可以在样式中设置Template属性:

<Style TargetType="Button">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="Template">
        <Setter.Value>
             <ControlTemplate TargetType="Button">
                 <Grid>
                     <Rectangle Fill="{TemplateBinding Background}"/>
                     <ContentPresenter/>
                 </Grid>
             </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

4
因此,您的示例完全适合我所想知道的问题...控件模板和仅定义一个控件模板的样式之间有什么区别?总是用Styles封装controltemplate是常见的吗?
斯蒂芬·罗兰

23

确实,您的确不对。 样式在控件上设置属性ControlTemplate是大多数控件共享的属性,这些控件指定如何呈现它们。

详细说来,您可以使用一种样式将一组属性的设置分组,以便您可以重复使用该样式来标准化控件。样式可以在控件上显式设置,也可以应用于某种特定类型。

控件模板可以通过样式设置,也可以在控件上显式设置以更改其显示方式。所有控件都具有嵌入在.net wpf程序集中的默认模板(以及相关样式)。看到这些并了解wpf开发人员如何实现所有控件的正常版本,这真是令人鼓舞。如果您安装了Expression blend,请查看其“ SystemThemes”文件夹。

更新:

了解样式和控件模板如何“添加控件”。以某种方式,ControlTemplate是定义控件所组成的控件的唯一方法。但是,某些默认的.net控件允许您使用控件代替文本。

例如:

<GroupBox>
  <GroupBox.Header>
    <CheckBox/>
  </GroupBox.Header>
</GroupBox>

这会将复选框“添加”到组框而不更改ControlTemplate,但这是因为默认ControlTemplate设置GroupBox允许将任何内容作为Header。这可以通过使用特殊控件(例如)来完成ContentPresenter

但是,有时控件的默认ControlTemplate不允许您更改要通过属性更改的内容。然后,您必须更改ControlTemplate。

无论直接设置还是通过样式设置控件的属性(内容,标题,ControlTemplate,IsEnabled等)都没有关系,样式只是一种方便。

希望这可以更清楚地回答您的问题。


1
好的,但是在我正在工作的项目中,两者都用于向其他控件中添加其他控件...以及设置属性...,所以我看不到它们的用法有何不同???
斯蒂芬·罗兰

2

在样式与模板之间的差异(msdn)中发现了一些有趣的差异

样式:只能在样式中设置预先存在的属性。例如,您不能为属于您添加到模板的新零件的属性设置默认值。

模板: 修改模板时,与修改样式相比,您可以访问控件的更多部分。例如,您可以更改弹出列表在组合框中的显示方式,也可以通过修改项目模板来更改触发组合框中的弹出列表的按钮的外观。


样式: 您可以使用样式来指定控件的默认行为。例如,在按钮样式中,您可以指定触发器,以便当用户将鼠标指针移到按钮上时,背景颜色将发生变化。这些属性更改是瞬时的(它们不能逐渐动画化)。

模板: 您可以使用触发器指定模板中任何新零件和现有零件的行为。例如,您可以指定一个触发器,以便当用户将鼠标指针移到按钮上时,部件之一的颜色将改变。这些属性更改可以是瞬时的,也可以是逐渐进行动画处理以产生平滑过渡的。


0

好的,我有完全相同的问题,在该线程中找到的答案将我引向正确的方向,所以我可以分享,如果可以的话,我可以自己更好地理解。

样式比ControlTemplate更灵活。

Windows Presentation Foundation Unleashed中,Adam Nathan和gang(作家)指出:

  • “除了将模板(带有使用样式的ControlTemplate设置器的样式)与任意属性设置组合在一起的便利性之外,这样做(在样式上设置ControlTemplate设置器)还有重要的优点:

    1. 它为您提供了默认模板的效果。例如,当默认情况下将类型化的样式应用于元素,并且该样式包含自定义控件模板时,将应用控件模板,而无需在这些元素上进行任何显式标记。
    2. 它使您能够提供控制模板外观的默认但可覆盖的属性值。换句话说,它使您能够尊重模板化父级的属性,但仍提供自己的默认值。”

换句话说,创建样式允许样式的“模板”设置器的用户覆盖设置的值,即使它们不使用TemplateBinding(例如,{TemplateBinding Width})也是如此。如果您在样式中对Width进行硬编码,则Style的用户仍可以覆盖它,但是如果您在Template中对Width属性进行硬编码,则用户会被它困住。

另外,当使用带有TemplateBinding的ContentTemplate时(这有点令人困惑),用户有责任设置该属性,否则它将对TargetType使用默认属性。如果使用样式,则可以通过以下方式覆盖TargetType的默认属性:对该属性使用设置器,然后将引用的TemplateBinding应用于该设置器。该书对此进行了更好的说明,第338页(使用样式混合模板)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.