2

在 WPF 渲染视觉元素之前,我需要计算它的逻辑宽度。

为了解释的简单,我会说这个视觉元素很可能是一个多边形对象。它可能是别的东西,但多边形可以很容易地可视化。

所以 XAML 可能看起来像这样:

<Window x:Class="MyCLRNamespace.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Window>

代码隐藏可能看起来像这样:

namespace MyCLRNamespace
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            //This is the visual element in question. It's a simple triangle.
            Polygon MyPolygon = new Polygon();
            MyPolygon.Points = new PointCollection {    new Point(100, 0),
                                                        new Point(200, 200),
                                                        new Point(0, 200)   };
            double PolyWidth = MyPolygon.Width;
            /* In this case, PolyWidth will be set to double.NaN, since
               MyPolygon.Width is never set.

               I need to be able to calculate the logical width of an element,
               unrelated to the WPF rendering system. This means that I can't
               rely on FrameworkElement.ActualWidth to calculate the width for
               me. I need to be able to look at the MyPolygon object (or its
               content) and figure out that it is set to a visual element that
               should be 200dips wide before any parent element applies any
               operations to it - regardless of what MyPolygon.Width may or may
               not be set to.

               It should also be noted that I don't have to rely on
               FrameorkElement. If there are more generic alternatives, such as
               the UIElement or Visual classes, I'd prefer to use those instead
               of the more specific FrameworkElement. The more robust I can make
               this, the better. */
        }
    }
}
4

2 回答 2

11

System.Windows.UIElement 类提供了在任何父子元素关系之外测量自身的方法。

在尝试使用测量值之前检查 IsMeasureValid 至关重要。如果 IsMeasureValid 为 false,则需要手动调用 UIElement.Measure() 方法以确保对元素及其内容进行最新测量。如果 IsMeasureValid 为真,那么再次测量不会有什么坏处。它只会覆盖它存储的任何以前的测量值。

如果您想要一个没有外部限制的元素的实体测量,请提供一个无限大小作为 UIElement.Measure() 方法的 availableSize 参数。

UIElement.Measure() 方法将元素的测量大小存储在 UIElement.DesiredSize 属性中。我不认为这对 WPF 渲染系统有任何负面影响,因为任何父元素都保证在渲染之前使用自己的可用大小限制重新测量元素。这可能会影响屏幕上元素的最终大小,但不会影响应用父子约束 之前元素的原始所需大小。

namespace MyCLRNamespace
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            Polygon MyPolygon = new Polygon();
            MyPolygon.Points = new PointCollection {    new Point(100, 0),
                                                        new Point(200, 200),
                                                        new Point(0, 200)   };
            //if (MyPolygon.IsMeasureValid == false)
                MyPolygon.Measure(new Size( double.PositiveInfinity,
                                            double.PositiveInfinity));

            double PolyWidth = MyPolygon.DesiredSize.Width;
        }
    }
}
于 2009-08-24T05:57:41.560 回答
0

唉,我们又见面了。如果你能告诉我们更多关于你想要达到的目标,也许会有所帮助。WPF 实际上使用与设备无关的单位来表示其大小,这就是 ActualWidth (来自 MSDN):

元素的宽度,以与设备无关的单位(每单位 1/96 英寸)表示的值。默认值为 0(零)。

如果您发现 ActualWidth 值的可用性异常,您可能需要收听SizeChangedevent 或 override OnRenderSizeChanged。我认为两者有细微的不同,但我不确定这些差异是什么。

于 2009-08-24T01:52:31.697 回答