如何计算WPF视觉元素的逻辑宽度?

发布于 2024-08-02 14:26:39 字数 1995 浏览 2 评论 0原文

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

为了简单起见,我会说这个视觉元素可能是一个 Polygon 对象。它可能是其他东西,但多边形使它更容易可视化。

因此,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. */
        }
    }
}

I need to calculate the logical width of a visual element, before it gets rendered by WPF.

For simplicity of explanation, I'll say that this visual element will likely be a Polygon object. It could be something else, but a Polygon makes it easy to visualize.

So the XAML might look something like this:

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

And the code-behind might look something like this:

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. */
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独﹏钓一江月 2024-08-09 14:26:39

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

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

如果您想要对元素进行可靠测量而没有外部限制,请提供无限大小作为 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;
        }
    }
}

The System.Windows.UIElement class provides methods for measuring itself outside of any parent-child element relationships.

It is critical that you check for IsMeasureValid before you attempt to use the measurement value(s). If IsMeasureValid is false, you need to manually call the UIElement.Measure() method to ensure that you have an up-to-date measurement the element and its content. If IsMeasureValid is true, it won't hurt to measure again. It will just overwrite any previous measurements it has stored.

If you want a solid measurement of the element with no outside restrictions, provide an infinite size as the availableSize parameter to the UIElement.Measure() method.

The UIElement.Measure() method will store the measured size of the element in the UIElement.DesiredSize property. I don't believe this has any negative impact on the WPF rendering system, due to the fact that any parent element is guaranteed to re-measure the element with its own available size constraints before rendering it. This may affect the final size of the element on screen, but it will not affect the original desired size of the element before parent-child constraints are applied.

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;
        }
    }
}
萌面超妹 2024-08-09 14:26:39

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

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

如果您发现 ActualWidth 值的可用性很奇怪,您可能需要监听 SizeChanged 事件或重写 OnRenderSizeChanged。我认为两者略有不同,但我不确定这些差异是什么。

Alas we meet again. Perhaps it would help if you tell us more about what you are trying to achieve. WPF actually uses device independent units for its sizes and that's what ActualWidth is (from MSDN):

The element's width, as a value in device-independent units (1/96th inch per unit). The default value is 0 (zero).

If you are seeing weirdness in availability of ActualWidth values you might want to listen to SizeChanged event or override OnRenderSizeChanged. I think the two are subtly different, but I am not sure what those differences are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文