如何绑定到控件的实际实际宽度(包括其边距)?

Kon*_*ten 5 c# data-binding wpf layout xaml

根据某些人的说法,实际宽度是使用ActualWidth属性获得的,如下例所示。这是有道理的,但我似乎遇到了自相矛盾的行为。

<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
  <Expander x:Name="Expy"
                    HorizontalAlignment="Left"
                    Margin="0,0,0,0"
                    VerticalAlignment="Top" ...>
  ...
  </Expander>
</Canvas>
Run Code Online (Sandbox Code Playgroud)

在上面的设置中,行为与预期一致,并且尽管紧密地挤压在一起,但包含画布的面板中的下一个元素并未与其前身重叠。

但是,如果将边距更改得更宽,我可以清楚地看到画布侵入到下一个元素,估计是由我在margin属性中请求的像素数相同。因此看来,ActualWidth不是实际宽度,而是没有边距的宽度。

  1. 我在这里有些困惑吗?
  2. 如何获取并绑定到actaully实际,呈现宽度?

在此处输入图片说明

Ste*_*nds 6

链接的答案说:

ActualWidth考虑填充和边距...

这是不正确的。在ActualWidth包括填充,而不是裕度(用相同ActualHeight)。

其他人在该答案上留下的评论提供了适当的更正。


此XAML代码说明了此问题:

<Window x:Class="..."
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <TextBlock x:Name="First" Text="Some text" Padding="10" Margin="0,0"
            HorizontalAlignment="Left" Background="Yellow" />
        <TextBlock Text="{Binding ActualWidth, ElementName=First}" />

        <TextBlock x:Name="Second" Text="Some text" Padding="10" Margin="10,0"
            HorizontalAlignment="Left" Background="LimeGreen" />
        <TextBlock Text="{Binding ActualWidth, ElementName=Second}" />
    </StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

如果运行此命令,则将看到两个“某些文本”文本块都具有相同的ActualWidth值,尽管第二个文本块已应用水平边距。


您问如何考虑到这一点。无法通过绑定来执行此操作,因为该ActualWidth属性不包括已声明的边距。您可以做的是将边距应用于父元素(画布),而不是将其应用于扩展器。

换句话说,而不是这样做:

<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
    <Expander x:Name="Expy" ... Margin="10" ... >
        ...
    </Expander>
</Canvas>
Run Code Online (Sandbox Code Playgroud)

做这个:

<Canvas Width="{Binding ActualWidth,ElementName=Expy}" Margin="10">
    <Expander x:Name="Expy" ... >
        ...
    </Expander>
</Canvas>
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,康拉德。你很困惑。

每当我们指的是实际(高度/宽度)时,它都是渲染的。你是对的。但是,实际(高度/宽度)值在 WPF 布局过程(包括测量和排列阶段)之后初始化,这是您首先需要了解的内容,才能找到问题的真正原因。

首先,将任何内容与实际值绑定永远不会给您带来所需的结果,因为这样做会违反 WPF 布局链。根据 WPF 布局阶段,在测量阶段,WPF 获取布局中每个控件的指定大小(例如,高度和宽度中指定的值),然后在排列阶段,它实际上以最佳方式将控件分配给布局。指定的大小在排列阶段后可能会发生变化。

另外,应该注意的是,实际参数包括渲染大小加上填充值(但不包括边距)。在您的示例中,我猜想 Expander 控件旁边的另一个面板是您报告的问题背后的原因。只有当我看到整个布局时我才能确认。

但作为预防措施,您始终可以停止使用实际参数进行绑定。您绝对可以使用绑定的宽度和高度值来解决它。

  • @KonradViltersten 在某些情况下绑定到“ActualWidth”(或“ActualHeight”)没有任何问题。许多人似乎在说,您可以做您想做的事,而无需绑定这些属性。然而,没有人展示任何支持这些论点的代码。我可能被证明是错误的,但我怀疑如果不使用外部网格元素使 XAML 复杂化*或* 显式设置扩展器控件的宽度,您将无法获得所需的布局。 (2认同)