如何在不引入副作用的情况下测量元素?

时间:2015-02-21 15:15:50

标签: wpf layout measure

如何让控件计算出最小尺寸要求,但不会影响它的当前状态或未来布局?

例如,假设我在网格中有一个StackPanel。 StackPanel的宽度将拉伸到网格宽度的大小。但是我怎样才能在不影响任何事情的情况下计算StackPanels的最小宽度。

查看Measure方法,它显示'Updates the DesiredSize of a UIElement. Calling this method constitutes the first pass (the "Measure" pass) of a layout update.'

所以这种方法有副作用。

3 个答案:

答案 0 :(得分:2)

我不相信在WPF中可以这样做。我想要完全相同的能力(测量给定约束,不会导致完整的测量/排列通过。

我做的一个实验是保存当前的DesiredSize,然后是InvalidateMeasure,然后是UpdateLayout,然后是Measure并查看DesiredSize。然后使用旧/保存的大小设置重做。不幸的是,它很慢并且我们的应用程序中有一个不好的副作用,即UpdateLayout()将运行事件循环来处理布局事件。这可能导致重新进行和处理其他不相关的排队事件,直到测量工作完成后我才想到这些事件。随之而来的是混乱。简而言之,这是IMO在WPF中的设计决策(缺陷?)。我开了一个UserVoice request恳求能够测量没有事件处理的布局。我预测它永远不会发生。

我已经使用了一个隐藏的窗口,其中包含我感兴趣的控件实例,没有任何内容(例如,空按钮)。我在安全时执行UpdateLayout并将所需大小作为“空”大小。我稍后使用该大小作为计算的一部分。我使用TextFormatter和GenericTextParagraphProperties自己测量文本,就像TextBlock一样。非常丑陋的代码只是为了避免消息循环并使控件不受影响!它也是脆弱的b / c模板更改将使我的计算无效。幸运的是,我完全控制了我需要测量的控件的模板。

答案 1 :(得分:0)

您可以根据microsoft提供的代码执行自己的计算,例如。 StackPanel:http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/Stack.cs,9ef706576207e5a6,references

然而,StackPanel使用他们孩子的Measure来计算自己的DesiredSize,所以自己计算这一切可能很困难。 我想你应该提供更多信息,为什么你不想影响现状。设置UIElement的DesiredSize有什么问题?

答案 2 :(得分:0)

我认为你可以在这里实现最好的方法是调用Measure方法。它确实有副作用,但如果你多次调用它,只有最后一个状态仍然有效。您不必担心视觉伪像,例如我们闪烁的临时布局。只会渲染最后一个。