wpf 如何绑定到控件的文字实际宽度(包括其边距)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28362036/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to bind to a control's literal actual width (including its margins)?
提问by Konrad Viltersten
According to some folks, the actual widthis obtained using ActualWidthattribute as shown in the example below. It makes sense but I seem to experience contradicting behavior.
根据某些人的说法,实际宽度是使用ActualWidth属性获得的,如下例所示。这是有道理的,但我似乎经历了矛盾的行为。
<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
<Expander x:Name="Expy"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top" ...>
...
</Expander>
</Canvas>
In the setup above, the behavior is consistent with the expectations and, although tightly squeezed together, the next element in the panel containing the canvas is not overlapped by it's predecessor.
在上面的设置中,行为与预期一致,尽管紧紧地挤在一起,包含画布的面板中的下一个元素没有与其前身重叠。
However, if I change the margins to a bit wider, I can clearly see that the canvas intrude on the next element, estimatingly by the same number of pixies that I requested in the margin attribute. So it'd appear that the ActualWidthisn't the actualwidth but the width without the margin.
但是,如果我将边距更改得更宽一些,我可以清楚地看到画布侵入了下一个元素,估计与我在边距属性中请求的像素数相同。所以看起来ActualWidth不是实际宽度,而是没有边距的宽度。
- Am I confusing something here and if so, what?
- How to obtain and bind to the actaullyactual, rendered width?
- 我是否在这里混淆了一些东西,如果是,那又是什么?
- 如何获取并绑定到actaully实际,呈现宽度?


回答by Steven Rands
The linked answer says:
链接的答案说:
ActualWidth accounts for padding and margins ...
ActualWidth 考虑了填充和边距......
This is incorrect. The ActualWidthincludes onlythe padding, not the margin (same with ActualHeight).
这是不正确的。在ActualWidth包括仅填充,而不是裕度(用相同ActualHeight)。
A comment that has been left on that answer by somebody else provides the appropriate correction.
其他人对该答案留下的评论提供了适当的更正。
This XAML code illustrates the issue:
此 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>
If you run this you will see that both of the "Some text" text blocks have the same ActualWidthvalue despite the second one having horizontal margins applied to it.
如果您运行它,您将看到两个“Some text”文本块具有相同的ActualWidth值,尽管第二个文本块应用了水平边距。
You asked how you could take this into account. There is no way of doing this through binding because the ActualWidthproperty doesn't include the margin as already stated. What you cando is apply the margin to the parent element (the canvas) instead of applying it to the expander.
你问你如何考虑这一点。没有办法通过绑定来做到这一点,因为该ActualWidth属性不包括已经说明的边距。您可以做的是将边距应用于父元素(画布)而不是将其应用于扩展器。
In other words, instead of doing this:
换句话说,不要这样做:
<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
<Expander x:Name="Expy" ... Margin="10" ... >
...
</Expander>
</Canvas>
do this:
做这个:
<Canvas Width="{Binding ActualWidth,ElementName=Expy}" Margin="10">
<Expander x:Name="Expy" ... >
...
</Expander>
</Canvas>
回答by Ashwin Masarkar
Yes Konrad. You are confusing.
是的,康拉德。你很困惑。
Whenever we mean Actual(Height/Width), it is the rendered one. You were correct in that. However, Actual(Height/Width) values gets initialized after the WPF Layout process which includes Measure and Arrange stages and that is something you need to understand first to get to the real cause of the problem.
每当我们指的是实际(高度/宽度)时,它就是渲染出来的。你是对的。但是,实际(高度/宽度)值在 WPF 布局过程(包括测量和排列阶段)之后被初始化,这是您首先需要了解的才能找到问题的真正原因。
At first, Binding anything with Actual values will never give you desired results because by doing this you are violating WPF Layout chain. As per WPF Layout stages, in Measure stage WPF gets the specified size (for e.g. values specified in height and width) for each control in the layout and then in the Arrange stage it actually allocates controls to the layout in the best possible way. The size specified is subject to vary after the Arrange stage.
起初,使用实际值绑定任何东西永远不会给你想要的结果,因为这样做你违反了 WPF 布局链。根据 WPF 布局阶段,在 Measure 阶段 WPF 获取布局中每个控件的指定大小(例如指定的高度和宽度值),然后在排列阶段,它实际上以最佳方式将控件分配给布局。指定的尺寸在编配阶段后会有所不同。
Also, it should be noted that Actual parameters include rendered size plus padding value (but not margin). In your example, I guess the other panel next to the Expander control is the reason behind the problem you reported. I can confirm only when I see the entire layout.
另外,应该注意的是,实际参数包括渲染大小加上填充值(但不包括边距)。在您的示例中,我猜扩展器控件旁边的另一个面板是您报告的问题背后的原因。只有当我看到整个布局时才能确认。
But as a precautionary measure, you can always stop using Actual parameters for bindings. You can definitely get it worked out using Width and Height values for binding.
但作为预防措施,您始终可以停止使用实际参数进行绑定。您绝对可以使用 Width 和 Height 值进行绑定。
回答by TT7
You cannot include the margin to your ActualWidth. A solution for this would be to use DesiredSize.Widthor DesiredSize.Height. This will take into account the Margin. But it's a UIElement.
您不能在ActualWidth. 对此的解决方案是使用DesiredSize.Widthor DesiredSize.Height。这将考虑保证金。但它是一个 UIElement。

