可能,我理解了一些根本错误的东西,但根据我所读到的内容,ControlTemplate-Property 允许我完全定义控件的外观,而无需更改其逻辑(如事件等)。
为了进行一些测试,我创建了一个空的 UWP 项目,并创建了一个具有拉伸(stretch)功能的按钮:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button HorizontalAlignment="Stretch"
Background="Red">
</Button>
</Grid>
正如预期的那样,按钮延伸到整个窗口。 现在,我用基本上完全相同的按钮覆盖模板,但作为模板:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button>
<Button.Template>
<ControlTemplate>
<Button HorizontalAlignment="Stretch"
Background="Red" />
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
在这种情况下,HorizontalAlignment 将被忽略。 由于我基本上用默认按钮模板(一个按钮)覆盖了按钮的外观,因此我预计会有相同的行为。我可以通过在 Button 本身上定义 HorizontalAlignment 然后使用 TemplateBinding 来修复它,但我不明白为什么它没有按预期被覆盖。
最佳答案
如果我们查看按钮的默认模板,它本质上是这样的(省略了一些诸如视觉状态之类的内容):
<Grid>
<ContentPresenter/>
</Grid>
检查实时可视化树中的按钮证实了这一点:
因此,您会发现网格取代了 Button 元素,Button 仍然是可视化树中的 Button,而是模板定义了 Button 的直接子级。
如果您将模板设置为以下内容:
<Button HorizontalAlignment="Stretch" Background="Red"/>
然后你会得到这个视觉树:
HorizontalAlignment 无法以这种方式工作的原因是它应用于内部按钮而不是外部按钮。作为布局过程的一部分,外部 Button(父级)决定内部 Button(子级)的大小和位置,并且由于父级未拉伸(stretch),因此它只能容纳显示按钮所需的最小尺寸。 child 。
就像你正在尝试这样做:
<Grid>
<Button>
<!-- This button won't stretch to the width of the Grid -->
<Button HorizontalAlignment="Stretch"/>
<Button>
</Grid>
将按钮的模板设置为按钮是没有意义的。看起来您想要做的是设置一个 Style,然后您可以为 Template 和父级的 HorizontalAlignment 设置一个 setter。
<Style x:Name="MyCustomButton" TargetType="Button">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
....
</ControlTemplate>
</Setter>
</Setter>
</Style>
如果要调整控件的模板,可以在 XAML 设计器中右键单击它 > 编辑模板 > 编辑副本。这会将该控件的默认样式拉入您的页面,然后您可以对其进行修改。
编辑
So, every Control, even without Template, has an appearance in the VisualTree and thus needs to be targeted?
我不确定“目标”是什么意思,但是是的,每个 Control 和 Control 派生类都有一个可以指定的模板。每个控件都有一个default style它设置控件的模板(以及其他属性)。我建议您引用Default control styles and templates如果您对这些风格感兴趣。
The Template then only overrides the "Content" of the Control?
没有。 ContentControl 的内容(例如按钮)与模板不同。将模板视为定义控件的整个视觉外观,将内容视为仅定义模板内某处外观的子集。例如,当您设置按钮的内容时,您并没有更改按钮的整个外观(按钮仍然具有边框和背景),您只是更改了按钮视觉中某个特定点处按钮内显示的内容树。这是ContentPresenter显示内容的控件(请参阅我的第一个屏幕截图)。
I didn't know I can see the Visual Tree, do I need a special version or such for that?
Visual Studio 提供实时可视化树功能已经有一段时间了(至少自 2015 年以来),因此除非您使用的是过时版本的 Visual Studio,否则您应该拥有该功能。
关于UWP:没有 ControlTemplate 的按钮的行为与有 ControlTemplate 的按钮不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40074976/