UWP:不带ControlTemplate的按钮与带ControlTemplate的按钮行为不同

UWP:不带ControlTemplate的按钮与带ControlTemplate的按钮行为不同,uwp,uwp-xaml,Uwp,Uwp Xaml,也许,我理解了一些根本错误的东西,但根据我所读的内容,ControlTemplate属性允许我完全定义控件的外观,而无需更改其逻辑(如事件等) 为了进行一些测试,我创建了一个空的UWP项目,并创建了一个带有stretch的按钮: 正如预期的那样,按钮在整个窗口中延伸。 现在,我用基本上完全相同的按钮覆盖模板,但作为模板: 在这种情况下,将忽略水平对齐。 因为我用默认的按钮模板,一个按钮来覆盖一个按钮的外观,所以我也期望有相同的行为。我可以通过在按钮本身上定义水平对齐来修复它,然后使用Te

也许,我理解了一些根本错误的东西,但根据我所读的内容,ControlTemplate属性允许我完全定义控件的外观,而无需更改其逻辑(如事件等)

为了进行一些测试,我创建了一个空的UWP项目,并创建了一个带有stretch的按钮:


正如预期的那样,按钮在整个窗口中延伸。 现在,我用基本上完全相同的按钮覆盖模板,但作为模板:


在这种情况下,将忽略水平对齐。
因为我用默认的按钮模板,一个按钮来覆盖一个按钮的外观,所以我也期望有相同的行为。我可以通过在按钮本身上定义水平对齐来修复它,然后使用TemplateBinding,但我不明白为什么它不会像预期的那样被覆盖。

如果我们查看按钮的默认模板,它本质上是这样的(省略了一些像视觉状态这样的内容):


检查实时视觉树中的按钮可以确认这一点:

因此,您可以看到网格并没有替换Button元素,Button仍然是可视化树中的一个按钮,而模板定义了按钮的直接子级

如果将模板设置为以下值:

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

然后,您将获得以下可视树:

水平对齐不能以这种方式工作的原因是它应用于内部按钮而不是外部按钮。作为布局过程的一部分,外部按钮(父按钮)决定内部按钮(子按钮)的大小和位置,并且由于父按钮未拉伸,因此它只能容纳显示子按钮所需的最小大小

就好像你想这么做:

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

将按钮的模板设置为按钮是没有意义的。看起来您想要做的是设置样式,然后您可以为模板和父对象的水平对齐设置一个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设计器>编辑模板>编辑副本中右键单击它。这将把该控件的默认样式拉入您的页面,然后您可以修改该页面


编辑

那么,每个控件,即使没有模板,也会在VisualTree中出现,因此需要有针对性

我不确定“targeted”是什么意思,但是是的,每个控件和控件派生类都有一个可以指定的模板。每个控件都有一个属性,用于设置控件的模板(以及其他属性)。如果你对这些款式感兴趣,我建议你参考

然后模板仅覆盖控件的“内容”

否。模板的内容(如按钮)与模板不同。将模板视为定义控件的整个视觉外观,将内容视为仅定义模板中某个位置的外观子集。例如,设置按钮的内容时,不会更改按钮的整个外观(按钮仍有边框和背景),只会更改按钮视觉树中某个特定点上按钮内部显示的内容。它是显示内容的控件(请参阅我的第一个屏幕截图)

我不知道我能看到可视化的树,我需要一个特别的版本吗

VisualStudio已经有了Live Visual Tree功能一段时间了(至少从2015年开始),因此您应该拥有该功能,除非您的VisualStudio版本已经过时


谢谢,我只是想用我的“按钮中的按钮”方法来测试行为。那么,每个控件,即使没有模板,也会在VisualTree中出现,因此需要有针对性?然后模板仅覆盖控件的“内容”?我不知道我能看到可视化树,我需要一个特别的版本吗?@MatthiasMüller:Live Visual树和Live Property Explorer都内置在Visual Studio 2015(任何版本)中,如下所述。@MatthiasMüller我已经编辑了关于您评论的答案。我们如何在C#code behind中实现这一逻辑,与样式、Setter属性模板类似
<Style x:Name="MyCustomButton" TargetType="Button">
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                ....
            </ControlTemplate>
        </Setter>
    </Setter>
</Style>