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

标签 uwp uwp-xaml

可能,我理解了一些根本错误的东西,但根据我所读到的内容,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>

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

最佳答案

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

<Grid>
    <ContentPresenter/>
</Grid>

检查实时可视化树中的按钮证实了这一点:

Screenshot

因此,您会发现网格取代了 Button 元素,Button 仍然是可视化树中的 Button,而是模板定义了 Button 的直接子级。

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

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

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

Screenshot

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

就像你正在尝试这样做:

<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 设计器中右键单击它 > 编辑模板 > 编辑副本。这会将该控件的默认样式拉入您的页面,然后您可以对其进行修改。


编辑

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,否则您应该拥有该功能。

Screenshot

关于UWP:没有 ControlTemplate 的按钮的行为与有 ControlTemplate 的按钮不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40074976/

相关文章:

xaml - UWP页面过渡动画

azure - 如何跟踪用户以获取基于位置的推送通知?

xaml - UWP , 制作 2 动画需要什么技能?

mvvm - UWP TextBox 文本绑定(bind)不起作用

c# - 文本 block 绑定(bind)不会在运行时更新

uwp - RaisePropertychanged 为 null,datacontext 改变后不通知属性

c# - 动态数据 : Sorting of bound list reloads on every change

连续操作 inkstrorkecontainer.clear() 和 addlines() 导致 UWP 中出现异常

xaml - UWP XAML : How to get an auto-sized Grid with equal column widths

wpf - 如何使滚动查看器在 WPF 中将高度设置为自动的情况下工作?