FramworkElement Организовать не размещение дочернего элемента FramworkElement - PullRequest
2 голосов
/ 08 ноября 2011

У меня есть два класса [применимо к этому вопросу]. Первый, XYAxes2, расширяется FrameworkElement. Он переопределяет MeasureOverride и ArrangeOverride в попытке поместить его единственного ребенка, XAxis (также расширяет FrameworkElement), в желаемое положение.

XYAxes2 (родитель):

Scale XAxis =//...
protected override Size MeasureOverride( Size availableSize ) {
    XAxis.Measure( availableSize );
    return (Size)availableSize;
}
protected override Size ArrangeOverride( Size finalSize ) {
    XAxis.Arrange( new Rect( 50, 50, 100, 200 ) );
    return finalSize;
}

Scale - это пользовательский нарисованный компонент. Scale (ребенок):

protected override void OnRender( DrawingContext cx ) {
    ValidateTicks();
    if (Orientation == Orientation.Horizontal) {
        cx.DrawLine( Pen, new Point( -.5, .5 ), new Point( ActualWidth - .5, .5 ) );
        foreach (double tick in _ticks.Keys) {
            double val = ScaleTransformCallback( tick );
            double x = -0.5 + (int)((val - MinValue) * ActualWidth / (MaxValue - MinValue));
            cx.DrawLine( Pen, new Point( x, .5 ), new Point( x, TickLength - .5 ) );
            FormattedText txt = _ticks[tick];
            cx.DrawText( txt, new Point( x - txt.Width / 2, TickLength + TextMargin ) );
        }
    } else {
        double Left = maxTextWidth + 2 * TextMargin;
        double Right = this.TickLength + Left;
        cx.DrawLine( Pen, new Point( Right - .5, +.5 ), new Point( Right - .5, ActualHeight + .5 ) );
        foreach (double tick in _ticks.Keys) {
            double val = ScaleTransformCallback( tick );
            double y = -0.5 + ActualHeight - (int)((val - MinValue) * ActualHeight / (MaxValue - MinValue));
            cx.DrawLine( Pen, new Point( Right - .5, y ), new Point( Left - .5, y ) );
            FormattedText txt = _ticks[tick];
            cx.DrawText( txt, new Point( Left - txt.Width - TextMargin, y - txt.Height / 2 ) );
        }
    }
}

При отладке, ActualWidth в этой функции всегда является шириной родительского элемента, а не ширины, установленной ArrangeOverride, 100. Однако дочерний элемент обрезается до области, заданной ArrangeOverride.

Я что-то не так делаю в одной из этих функций?

Редактировать: Вставив XAxis.Measure(100,200) в ArrangeOverride, проблема, по-видимому, исправлена. Конечно, нет необходимости вызывать Measure каждый раз, когда соглашение становится недействительным (это будет означать, что InvalidateArrange потребуется неявно вызывать InvalidateMeasure). Кто-нибудь может пролить свет на причины этого?

Кто-нибудь знает, где на самом деле установлены DesiredSize и ActualWidth/Height (очевидно, они не установлены моим кодом)?

1 Ответ

1 голос
/ 10 ноября 2011

Решение, которое я использовал для этого, заключается в использовании нескольких проходов в функции MeasureOverride.Я продолжаю измерения с различными размерами, пока не будет определен подходящий общий размер.

При чтении исходного кода .Net 4.0 получается, что: -

  • DesiredSizeустанавливается функцией UIElement.Measure в качестве возвращаемого значения MeasureOverride.

  • ActualWidth / ActualHeight (RenderSize) устанавливается в FrameworkElement.ArrangeCore каккакое бы значение не возвращалось из ArrangeOverride Похоже, что нет никакой проверки ошибок или округления.

Я надеюсь, что это может помочь другим людям.

...