FramworkElement 安排不放置子 FramworkElement

发布于 2024-12-14 03:22:04 字数 2460 浏览 0 评论 0原文

我有两节课[适用于这个问题]。第一个 XYAxes2 扩展了 FrameworkElement。它会覆盖 MeasureOverrideArrangeOverride,试图将其唯一的子元素 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)。谁能解释一下这背后的原因吗?

有谁知道 DesiredSizeActualWidth/Height 实际设置在哪里(显然它们不是由我的代码设置的)?

I have two classes [applicable to this question]. The first, XYAxes2, extends FrameworkElement. It overrides MeasureOverride and ArrangeOverride in an attempt to place it's sole child, XAxis (also extends FrameworkElement), in the desired position.

XYAxes2 (Parent):

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 is a custom drawn component.
Scale (Child):

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

When debugging, ActualWidth in this function is always the width of the parent rather than the width set by ArrangeOverride, 100. The child is, however, clipped to the region specified by ArrangeOverride.

Am I do something wrong in one of these functions?

Edit: By inserting XAxis.Measure(100,200) into ArrangeOverride, the problem is apparently fixed. Surely, it shouldn't be necessary to call Measure everytime the arrangement is invalidated (this would mean InvalidateArrange would need to implicitly call InvalidateMeasure). Can anyone shed any light on the causes behind this?

Does anyone know where DesiredSize and ActualWidth/Height are actually set (obviously they are not set by my code)?

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

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

发布评论

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

评论(1

世界等同你 2024-12-21 03:22:04

我为此使用的解决方案是在 MeasureOverride 函数中使用多次传递。我不断测量不同的尺寸,直到确定合适的整体尺寸。

通过阅读 .Net 4.0 源代码,可以看出:-

  • DesiredSizeUIElement.Measure 函数设置为
    MeasureOverride 的返回值。

  • ActualWidth/ActualHeight (RenderSize) 由以下设置
    FrameworkElement.ArrangeCore 是从返回的任何值
    ArrangeOverride 似乎没有任何错误检查或
    应用舍入。

我希望这可以帮助其他人。

The solution I have used for this is to use multiple passes in the MeasureOverride function. I keep measuring with different sizes until a suitable overall size is determined.

By reading through the .Net 4.0 source code, it appears that :-

  • DesiredSize is set by the UIElement.Measure function to be the
    return value of MeasureOverride.

  • ActualWidth/ActualHeight (RenderSize) are set by
    FrameworkElement.ArrangeCore to be whatever value is returned from
    ArrangeOverride There doesn't appear to be any error checking or
    rounding applied.

I hope this can help other people.

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