WPF中的Width和ActualWidth有啥区别?
Posted
技术标签:
【中文标题】WPF中的Width和ActualWidth有啥区别?【英文标题】:What is the difference between Width and ActualWidth in WPF?WPF中的Width和ActualWidth有什么区别? 【发布时间】:2010-10-11 02:32:06 【问题描述】:我目前在 WPF 中使用Panel
s,我注意到关于Width
和Height
属性,还有另外两个属性称为ActualWidth
和ActualHeight
。
ActualWidth
获取 this 的渲染宽度 元素。这是一个依赖 财产。 (继承自 框架元素。)
Width
获取或设置元素的宽度。 这是一个依赖属性。 (继承自 FrameworkElement。)
参考:MSDN
谁能指出两者之间的区别以及何时使用其中任何一个?
【问题讨论】:
【参考方案1】:Width
/Height
是请求或布局的大小。如果您设置为 Auto,那么当您在后面的代码中访问该属性时,该值为 double.NaN
。
ActualWidth
/ActualHeight
和 RenderSize.Width
/RenderSize.Height
都返回元素的渲染大小,因为 RenderSize 是 Size 类型。如果您想要/需要项目的实际大小,请使用这些属性中的任何一个。
【讨论】:
实际上是布局大小而不是渲染大小。 @chuckj,使用什么属性来获取渲染大小? @dumbledad.RenderSize.Width
【参考方案2】:
有一个很好的理由不使用ActualWidth
来绑定(显然是ActualHeight
)。
当您将一个元素的Width
设置为另一个元素的ActualWidth
时,您可能破坏布局链。
在最好的情况下,您的元素/控件需要在父(绑定源)的布局过程完成后进行解析。这意味着额外的时间。 如果它与父级处于相同的层次结构级别,则布局过程需要(至少)两次运行才能计算确定的大小。
例如,我有一个控件,它的 size 属性被覆盖为一种样式,将其设置为 TemplatedParent
(不要这样做):
<Rectangle DockPanel.Dock="Top" Width="TemplateBinding ActualWidth"
Height="1" Fill="#000000"/>
当调整包含窗口的大小时,控件会阻止容器变小并破坏布局。将其设置为Width
将解决问题(do):
<Rectangle DockPanel.Dock="Top" Width="TemplateBinding Width"
Height="1" Fill="#000000"/>
如果您必须使用ActualWidth
,通常您的 xaml 有问题。更好地解决这个问题,而不是弄乱布局运行的最终大小。
【讨论】:
你的代码sn-ps(“dont do”和“do”)完全一样?!?! 感谢您的评论。解决了这个问题。 @tuner 我不同意这一点:“如果你必须使用 ActualWidth 通常你的 xaml 有问题”。绑定到ActualWidth
(或ActualHeight
)没有任何问题,实际上在某些情况下,这可能是解决特定布局问题的最简单方法。仅仅因为绑定到这些属性会在(罕见的)场合引起问题,并没有理由完全避免它们。
@StevenRands :您的罕见情况的问题是很难找到问题的根源。如果将确定组件大小的属性绑定到ActualWidth
或类似属性,则至少需要两次布局传递才能确定组件的大小。我个人的经验是,这首先有效。然后,在引入其他非标准行为(确实如此)之后,事情就会中断,而您在确定它时遇到了真正的问题。
@tuner 我已经多次使用这种技术,但从未遇到过您提到的任何问题。也许我只是幸运。有些地方我不会使用它,但我认为基本上说“使用它而你做错了”的笼统声明没有帮助。我同意你关于多个布局传递的观点,但我认为这种绑定通常是 XAML 中最简单的说法:我希望 this 元素与 具有相同的宽度(或高度)那个元素。无论如何只是一个意见。【参考方案3】:
ActualWidth
占值的填充,因此任何时候您需要知道该数字,您都可以调用Actualwidth
而不是宽度并避免计算。
编辑:删除 Margin b/c 它不是 ActualWidth 的一部分。
【讨论】:
【参考方案4】:当我想将一个元素的宽度或高度绑定到另一个元素时,我发现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>
【讨论】:
【参考方案5】:您可以设置Width
属性,但不能设置ActualWidth
属性。
Width
属性用于确定面板的呈现方式,然后将ActualWidth
设置为所使用的实际宽度。这可能与 Width 的值不同,具体取决于其子元素的大小及其父元素的限制。
ActualWidth
在设置Width
属性时不会立即设置,但会在渲染期间更新(一次或多次)。
【讨论】:
【参考方案6】:就是这样,渲染宽度!= 布局宽度。一个用于布局,另一个用于渲染。与 WinForms 一样,有 Size 和 ClientSize 属性,略有不同,您应该使用 Atual/Client 的渲染大小和 Width/Height 进行布局。
【讨论】:
【参考方案7】:ActualWidth
由渲染系统设置,可能会根据其他元素的宽度和整体大小限制而有所不同。结果,它无法更改。 Width
是一个可以改变的属性,应该用来增加或减少元素的宽度。
来自MSDN:
此属性是根据其他宽度输入和布局系统计算得出的值。该值由布局系统本身根据实际渲染过程设置,因此可能会稍微落后于作为输入更改基础的属性(例如
Width
)的设置值。
【讨论】:
以上是关于WPF中的Width和ActualWidth有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
如何绑定只读的 WPF 控件属性(例如 ActualWidth),以便在视图模型中可以访问其值? [复制]
Java 中 给一个object 赋值属性, 既可以用构造函数的方式,也可以用setXXXX()的方式,而它们之间有啥区