WPF:为什么我不应该在ControlTemplate中使用{TemplateBinding Margin} - Margin只适用于元素的容器吗?

9

我已经为按钮创建了自己的ControlTemplate,就像这样:

<Style x:Key="LightButtonStyle" TargetType="{x:Type ButtonBase}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ButtonBase}">
                <Border
                    x:Name="WrappingBorder"
                    Margin="{TemplateBinding Margin}"
                    ...
                    >
                    <ContentPresenter 
                        Content="{TemplateBinding Content}" 
                        ...
                        >
                    </ContentPresenter>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在,我注意到当我给我的按钮设置外边距时,例如:
<Button 
    Style="{StaticResource LightButtonStyle}"
    Margin="20"
    >
    Hello world!
</Button>

按钮实际上具有双倍的Margin - 40。我认为控件实际上应该从不使用Margin属性,并且在排列阶段,Margin属性只能被按钮的祖先读取。然后,我查看了WPF默认样式,并发现没有一个使用Margin。这是正确的结论吗(即Margin仅用于由容器正确排列)?换句话说,每次我在我的样式中使用{TemplateBinding Margin}时,我会得到双倍的边距吗?还有一些类似属性的列表,我的控件不应该使用吗(因为它们仅适用于“周围的世界”)?你能指向解释这个的MSDN页面吗?谢谢!

我猜我应该在http://msdn.microsoft.com/en-us/library/ms745058.aspxhttp://msdn.microsoft.com/en-us/library/ms751709.aspx中寻找答案,但我认为它们没有明确提到控件从不使用Margin属性,而是总是祖先或wpf系统来评估并使用它来影响布局...

2个回答

8

你的结论是正确的,如果你查看框架提供的默认模板,你会发现模板中的 Margin 与控件的 Padding 属性绑定。


谢谢,我注意到了这个问题... 你知道一些 MSDN 页面或博客文章可以解释 Margin(和其他布局特定属性)在布局中的作用吗?我尝试过谷歌搜索,但没有找到真正的答案。 - Tomáš Kafka
1
我相信谷歌可以帮助你,但我会说(或者写)一件事。Margin是布局过程中容器在排列传递中使用的,容器将根据其水平和垂直对齐以及其margin将子元素放置在一个位置上。 - Aviad P.
谢谢,这正是我想要的 - 除了 Margin 外,我还应该永远不在模板中使用 s HorizontalAlignment 和 VerticalAlignment。 - Tomáš Kafka

6

Margin是由布局系统自动应用的,在控件模板内应使用Padding代替。

<Border x:Name="WrappingBorder" Margin="{TemplateBinding Padding}" ... />

Aviad先回复了(并在稍后的评论中暗示了边距应用的阶段),因此我接受了他的答案 - 但也非常感谢你! - Tomáš Kafka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接