Как рассчитать логическую ширину визуального элемента WPF? - PullRequest
2 голосов
/ 24 августа 2009

Мне нужно вычислить логическую ширину визуального элемента, прежде чем он будет визуализирован WPF.

Для простоты объяснения я скажу, что этот визуальный элемент, скорее всего, будет объектом Polygon. Это может быть что-то еще, но 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. */
        }
    }
}

Ответы [ 2 ]

11 голосов
/ 24 августа 2009

Класс System.Windows.UIElement предоставляет методы для измерения себя вне любых отношений родительских и дочерних элементов.

Очень важно проверить IsMeasureValid, прежде чем пытаться использовать значения измерений. Если IsMeasureValid имеет значение false, необходимо вручную вызвать метод UIElement.Measure (), чтобы убедиться, что у вас есть актуальное измерение элемента и его содержимого. Если IsMeasureValid имеет значение true, измерение не повредит. Он просто перезапишет все предыдущие измерения, которые он сохранил.

Если требуется точное измерение элемента без внешних ограничений, укажите бесконечный размер в качестве параметра availableSize для метода UIElement.Measure ().

Метод UIElement.Measure () сохраняет измеренный размер элемента в свойстве UIElement.DesiredSize. Я не верю, что это оказывает какое-либо негативное влияние на систему рендеринга WPF из-за того, что любой родительский элемент гарантированно повторно измеряет элемент с собственными доступными ограничениями размера перед его рендерингом. Это может повлиять на конечный размер элемента на экране, но не повлияет на исходный желаемый размер элемента до применения ограничений parent-child.

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;
        }
    }
}
0 голосов
/ 24 августа 2009

Увы, мы снова встретимся. Возможно, это поможет, если вы расскажете нам больше о том, чего вы пытаетесь достичь. WPF фактически использует независимые от устройства единицы для своих размеров, и вот что такое ActualWidth (из MSDN):

Ширина элемента в виде значения в независимых от устройства единицах (1/96 дюйма на единицу). Значением по умолчанию является 0 (ноль).

Если вы видите странность в наличии значений ActualWidth, вы можете прослушать событие SizeChanged или переопределить OnRenderSizeChanged. Я думаю, что они немного отличаются друг от друга, но я не уверен, что это за различия.

...