How do I calculate the logical width of a WPF visual?

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

For the sake of simplicity, I'll say that this visual is most likely a Polygon object. It might be something different, but Polygon makes it easier to render.

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

      

+2


source to share


2 answers


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

It is very important that you check IsMeasureValid before attempting to use measured values. If IsMeasureValid is false, you need to manually call the UIElement.Measure () method to ensure that you have the last dimension of the element and its content. If IsMeasureValid is true, it doesn't hurt to measure again. It will simply overwrite any previous measurements that it has saved.

If you want a solid dimension of an element without outside constraints, specify an infinite dimension as a parameter of an available parameter to the UIElement.Measure () method.



The UIElement.Measure () method will store the measured size of the element in the UIElement.DesiredSize property. I do not believe this will negatively impact the WPF rendering system because any parent element is guaranteed to resize the element with its own 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 the parent and child constraints.

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;
        }
    }
}

      

+10


source


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

Item width as a value in device agnostic devices (1 / 96th inch per unit). The default is 0 (zero).



If you see an oddity in the availability of ActualWidth values, you can listen to the event SizeChanged

or override OnRenderSizeChanged

. I think the two are subtly different from each other, but I'm not sure what those differences are.

0


source







All Articles