UWP:没有ControlTemplate的按钮与一个按钮的行为不同

时间:2016-10-16 20:13:05

标签: uwp uwp-xaml

也许,我理解一些根本错误的东西,但根据我所读到的,ControlTemplate-Property允许我完全定义Control的外观而不改变它的逻辑,比如事件等。

对于某些测试,我创建了一个空的UWP-Project,并创建了一个带有拉伸的按钮:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button HorizontalAlignment="Stretch" 
            Background="Red">
    </Button>
</Grid>

正如预期的那样,Button会拉伸整个Window。 现在,我用基本上完全相同的Button覆盖模板,但是模板:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button>
        <Button.Template>
            <ControlTemplate>
                <Button HorizontalAlignment="Stretch" 
                        Background="Red" />
            </ControlTemplate>
        </Button.Template>
    </Button>
</Grid>

在这种情况下,Horizo​​ntalAlignment将被忽略。 由于我基本上使用默认按钮模板,按钮覆盖Button的外观,因此我预计会出现相同的行为。我可以通过在Button本身上定义Horizo​​ntalAlignment然后使用TemplateBinding来修复它,但我不明白为什么它不会像预期的那样被覆盖。

1 个答案:

答案 0 :(得分:2)

如果我们查看Button的默认模板,它本质上是这样的(有些东西比如省略了视觉状态):

<Grid>
    <ContentPresenter/>
</Grid>

检查Live Visual Tree中的按钮确认了这一点:

Screenshot

所以你看到Grid没有替换 Button元素,Button仍然是可视树中的Button,而模板定义了Button的直接子节点是什么

如果您将模板设置为以下内容:

<Button HorizontalAlignment="Stretch" Background="Red"/>

然后你会得到这个可视树:

Screenshot

Horizo​​ntalAlignment不以这种方式工作的原因是因为它应用于内部按钮而不是外部按钮。作为布局过程的一部分,外部Button(父级)决定了内部Button(子级)的大小和位置,并且由于父级没有被拉伸,因此它只能容纳所需的最小大小。展示孩子。

它就像你在尝试这样做:

<Grid>
    <Button>
        <!-- This button won't stretch to the width of the Grid -->
        <Button HorizontalAlignment="Stretch"/>
    <Button>
</Grid>

将按钮的模板设置为按钮没有意义。看起来你要做的就是设置一个Style,然后你可以为Template和父对象的Horizo​​ntalAlignment设置一个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设计器中右键单击它&gt;编辑模板&gt;编辑副本。这会将该控件的默认样式引入到您可以修改的页面中。

修改

  

因此,即使没有模板,每个Control都在VisualTree中出现,因此需要进行定位?

我不确定你的意思是&#34;有针对性的&#34;,但是,是的,每个Control和Control派生类都有一个可以指定的模板。每个Control都有一个default style,用于设置控件的模板(以及其他属性)。如果您对这些风格感兴趣,我会推荐您Default control styles and templates

  

模板然后只覆盖&#34;内容&#34;控制?

没有。 ContentControl(例如按钮)的内容与模板不同。可以将模板视为定义控件的整个视觉外观,将内容视为仅定义模板中某个外观的子集。例如,当你设置按钮的内容时,你并没有改变按钮的整个外观(按钮仍然有边框和背景),你只改变了按钮内部显示的内容。按钮的可视树中的特定点。它是显示内容的ContentPresenter控件(请参阅我的第一个屏幕截图)。

  

我不知道我可以看到Visual Tree,我需要特殊版本吗?

Visual Studio已经有一段时间的Live Visual Tree功能(至少从2015年开始),所以除非你有一个过时的Visual Studio版本,否则你应该拥有该功能。

Screenshot