【发布时间】:2011-09-02 10:23:48
【问题描述】:
您能告诉我 Style 和 ControlTemplate 之间的主要区别是什么吗? 何时或为何使用其中一种?
在我看来,它们完全相同。由于我是初学者,我认为我错了,所以我的问题。
【问题讨论】:
-
MSDN 资源,样式和模板的区别:msdn.microsoft.com/en-us/library/…
您能告诉我 Style 和 ControlTemplate 之间的主要区别是什么吗? 何时或为何使用其中一种?
在我看来,它们完全相同。由于我是初学者,我认为我错了,所以我的问题。
【问题讨论】:
在样式中,您可以设置控件的属性。
<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}"/>
使用此模板的所有按钮都将具有无法更改的绿色背景。
模板中设置的值只能通过替换整个模板来替换。 style 中的值可以通过在使用控件时显式设置值来替换。这就是为什么通过使用 TemplateBinding 而不是编码值来更好地使用控件的属性的原因。
<ControlTemplate x:Key="MyButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
现在模板使用它应用到的按钮的背景属性的值,所以可以自定义:
<Button Template="{StaticResource MyButtonTemplate}" Background="Yellow"/>
另一个有用的功能是控件可以选择默认样式,而无需为其分配特定样式。模板无法做到这一点。
只需删除样式的 x:Key 属性(同样:您不能对模板执行此操作)。样式下方可视树中的所有按钮都将应用此样式。
结合模板和样式更加强大:您可以在样式中设置模板属性:
<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>
【讨论】:
不,你确实错了。 样式集属性在控件上。 ControlTemplate 是大多数控件共享的属性,用于指定它们的呈现方式。
详细地说,您可以使用一种样式对一组属性的设置进行分组,以便您可以重复使用它来标准化您的控件。样式可以在控件上显式设置,也可以应用于某个类型。
控件模板可以通过样式设置或在控件上显式设置以更改其显示方式。所有控件都具有嵌入在 .net wpf 程序集中的默认模板(和样式)。看到这些并了解 wpf 开发人员如何实现所有控件的正常版本是非常有启发性的。如果您安装了 Expression blend,请查看其“SystemThemes”文件夹。
更新:
了解 Styles 和 ControlTemplates 如何“添加控件”。在某种程度上,ControlTemplate 是定义控件组成的控件的唯一方法。但是,一些默认的 .net 控件允许您使用控件代替文本。
例如:
<GroupBox>
<GroupBox.Header>
<CheckBox/>
</GroupBox.Header>
</GroupBox>
这会在不更改ControlTemplate 的情况下向组框“添加”一个复选框,但这是因为GroupBox 的默认ControlTemplate 允许将任何内容作为标题。这是通过使用特殊控件(例如ContentPresenter)来完成的。
但是,有时控件的默认 ControlTemplate 不允许您更改要通过属性更改的内容。然后您必须更改 ControlTemplate。
无论您是直接设置控件的属性(Content、Header、ControlTemplate、IsEnabled 等)还是通过样式设置都无所谓,样式只是一种方便。
希望这能更清楚地回答您的问题。
【讨论】:
您可以将样式视为将一组属性值应用于多个元素的便捷方式。您可以通过直接在每个 TextBlock 元素上设置属性(例如 FontSize 和 FontFamily)来更改默认外观。但是,如果您希望 TextBlock 元素共享某些属性,则可以在 XAML 文件的资源部分中创建样式。
另一方面,ControlTemplate 指定控件的视觉结构和视觉行为。您可以通过给它一个新的 ControlTemplate 来自定义控件的外观。创建 ControlTemplate 时,您替换现有控件的外观而不更改其功能。例如,您可以将应用程序中的按钮设为圆形而不是默认的方形,但按钮仍会引发 Click 事件。
【讨论】:
我发现了一些有趣的差异 The difference between styles and templates (msdn)
风格: 您可以在样式中设置仅预先存在的属性。例如,您不能为属于您添加到模板的新部件的属性设置默认值。
模板: 修改模板时,您可以访问控件的更多部分,而不是修改样式时。例如,您可以更改弹出列表在组合框中的显示方式,或者通过修改项目模板来更改触发组合框中弹出列表的按钮的外观。
风格: 您可以使用样式来指定控件的默认行为。例如,在按钮的样式中,您可以指定触发器,以便当用户将鼠标指针移到按钮上时,背景颜色会发生变化。这些属性更改是瞬时的(它们不能逐渐动画)。
模板: 您可以使用触发器指定模板中任何新部件和现有部件的行为。例如,您可以指定一个触发器,以便当用户将鼠标指针移到按钮上时,其中一个部分的颜色会发生变化。这些属性更改可以是瞬时的或逐渐动画化以产生平滑的过渡。
【讨论】:
好的,我有完全相同的问题,我在这个帖子中找到的答案为我指明了正确的方向,所以我分享一下,如果我自己能更好地理解它。
Style 比 ControlTemplate 更灵活。
来自 Windows Presentation Foundation Unleashed,Adam Nathan 和帮派(作家)声明:
“除了将模板 [与使用 Style 的 ControlTemplate 设置器的样式] 与任意属性设置组合起来很方便之外,这样做[在样式上设置 ControlTemplate 设置器] 还有一些重要的优点:
换句话说,创建样式允许样式模板设置器的用户覆盖设置的值,即使他们没有使用 TemplateBinding(例如 {TemplateBinding Width})。如果您在样式中硬编码 Width,则 Style 的用户仍然可以覆盖它,但如果您在模板中硬编码 Width 属性,用户就会被它卡住。
此外,(这有点令人困惑)当使用带有 TemplateBinding 的 ContentTemplate 时,用户有责任设置该属性,否则它将使用 TargetType 的默认属性。如果使用样式,则可以通过使用属性的 setter 并应用 TemplateBinding 引用回该 setter 来覆盖 TargetType 的默认属性。这本书更好地解释了它,第 338 页(将模板与样式混合)
【讨论】: