WPF中Width和ActualWidth有什么区别?

52
我目前在WPF中使用Panel,发现关于WidthHeight属性,还有另外两个属性叫做ActualWidthActualHeight

ActualWidth

获取此元素的渲染宽度。这是一个依赖属性。(从FrameworkElement继承。)

Width

获取或设置元素的宽度。这是一个依赖属性。(从FrameworkElement继承。)

参考: MSDN

有人能指出两者之间的区别以及何时使用哪一个吗?
7个回答

79

Width/Height 是请求或布局尺寸。如果将其设置为自动,则在后台代码访问该属性时,该值为 double.NaN

ActualWidth/ActualHeightRenderSize.Width/RenderSize.Height 都返回元素的渲染大小,因为RenderSizeSize类型。如果您需要获取项目的实际大小,则使用这些任意属性。


8
实际上是指布局大小而非渲染大小。 - chuckj
2
@chuckj,想获取渲染尺寸的属性应该使用哪个? - dumbledad
2
@dumbledad .RenderSize.Width @dumbledad .RenderSize.Width - Mafii

11

当我想将一个元素的宽度或高度绑定到另一个元素时,我发现ActualWidth最有用。

在这个简单的例子中,我有两个按钮并排排列,下面有一条注释,该注释被限制在包含这两个按钮的StackPanel的宽度内。

<StackPanel>

    <StackPanel Margin="0,12,0,0" Orientation="Horizontal" Name="buttonPanel" HorizontalAlignment="Left" >
         <Button Content="Yes - Arm the missile" FontWeight="Bold" HorizontalAlignment="Left"/>
         <Button Content="No - Save the world" HorizontalAlignment="Left" Margin="7,0,0,0"/>
    </StackPanel>

    <TextBlock Text="Please choose whether you want to arm the missile and kill everybody, or save the world by deactivating the missile." 
               Width="{Binding Path=ActualWidth,ElementName=buttonPanel}" Margin="0,5,0,0" HorizontalAlignment="Left" TextWrapping="Wrap"/>

</StackPanel>

7
< p > ActualWidth 考虑到填充值,因此每次需要知道该数字时,您可以调用Actualwidth而不是宽度并避免计算。

编辑:删除Margin b / c,因为它不是ActualWidth的一部分。


3

不要使用ActualWidth(显然,ActualHeight也一样)绑定元素的宽度,这是非常明智的选择,因为这可能会破坏布局链

在最好的情况下,您的元素/控件需要在父级的布局过程完成后进行解析。这意味着需要额外的时间。 如果它与父级处于同一层次结构,布局过程需要至少两次运行才能计算出一个确定的大小。

例如,我有一个控件,它的大小属性被覆盖在一个样式中,该样式将其设置为TemplatedParent(不要这样做)

<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding ActualWidth}" 
           Height="1" Fill="#000000"/>

当调整容器窗口大小时,控件会防止容器变得更小并破坏布局。将其设置为宽度(Width)将解决这个问题(完成)

<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding Width}" 
           Height="1" Fill="#000000"/>

如果你必须使用ActualWidth,通常意味着你的XAML存在问题。最好修复它,而不是在布局运行的最终大小上搞乱。

1
你的代码片段(“不要做”和“做”)完全一样?!? - PIntag
感谢您的评论。已经修复了。 - Pascal
2
@tuner 我不同意这个观点:“如果你必须使用ActualWidth,通常意味着你的xaml存在问题”。绑定到ActualWidth(或ActualHeight)没有任何问题,事实上,在某些情况下,这可能是解决特定布局问题最简单的方法。仅仅因为绑定到这些属性在(很少见的)情况下会导致问题,这并不是完全避免它们的理由。 - Steven Rands
2
@StevenRands:你偶尔使用的问题在于很难找到问题的源头。如果将决定组件大小的属性绑定到“ActualWidth”或类似属性,则需要至少进行两次布局传递才能确定组件的大小。我的个人经验是,这起初是有效的。然后,在引入其他非标准行为(即使它是正确的)之后,事情会出现问题,你真正需要解决它。 - Pascal
1
@tuner 我已经使用过这种技术很多次,从来没有遇到你提到的任何问题。也许我只是幸运。有些地方我不会使用它,但我认为一个笼统的陈述基本上是“如果你使用这个,你就做错了”并不是很有帮助。我理解你关于多次布局传递的观点,但我认为这种绑定通常是在XAML中表达“我想要这个元素与那个元素具有相同的宽度(或高度)”最简单的方法。无论如何,这只是我的观点。 - Steven Rands
显示剩余2条评论

3
ActualWidth是由渲染系统设置的,可能会因其他元素的宽度和整体尺寸限制而有所不同。因此,它不能被更改。Width是一个可以更改的属性,应该用来增加或减小元素的宽度。
MSDN得知:
这个属性是基于其他宽度输入和布局系统的计算值。该值由布局系统本身设置,基于实际的渲染通道,因此可能会稍微滞后于诸如Width之类的属性的设置值,这些属性是输入更改的基础。

0

确切地说,渲染宽度 != 布局宽度。一个用于布局,另一个用于渲染。就像在 WinForms 中一样,有一个 Size 和一个 ClientSize 属性,它们略有不同,您应该使用渲染的 Atual/Client 大小和布局的 Width/Height。


0

您可以设置Width属性,但不能设置ActualWidth属性。

Width属性用于确定面板的呈现方式,然后将ActualWidth设置为实际使用的宽度。这可能与宽度不同,具体取决于其子元素的大小和父元素的限制。

在设置Width属性时,ActualWidth不会立即设置,但会在呈现过程中更新一次或多次。


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