在WPF中,如何在实际渲染之前获取控件的渲染大小?

Mar*_*eIV 7 wpf layout rendering resize render

我在Decorator子类中进行自定义渲染.我们的渲染需要创建复杂的几何体,只有当实际渲染的尺寸发生变化时才会重新创建.因此,我已将几何创建移动到其自己的函数中UpdateGeometry,该函数创建,然后冻结几何体以供使用OnRender.只需要响应ActualWidthor中的更改来调用此新函数ActualHeight.

更好的是,看起来我们应该能够简单地覆盖OnRenderSizeChanged,根据文档说明......

"在派生类中重写时,参与由布局系统指导的渲染操作.在布局更新之后和渲染之前,如果元素的RenderSize由于布局更新而发生更改,则调用此方法."

但是,如果不管我使用的覆盖或听的属性更改通知ActualWidthActualHeight,我的记录一致表明OnRender作为第一个发生!嗯......什么?

为了确保它不是我在我的代码中所做的事情,我创建了一个简单的测试装饰器子类并在那里添加了日志记录,在进入和退出到覆盖.这是全班......

using System;
using System.Windows.Controls;

public class TestControl : Decorator
{

    protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
    {
        Console.WriteLine("OnRender Entered");

        base.OnRender(drawingContext);

        Console.WriteLine("OnRender Exited");
    }

    protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
    {
        Console.WriteLine("OnRenderSizeChanged Entered");

        base.OnRenderSizeChanged(sizeInfo);

        Console.WriteLine("OnRenderSizeChanged Exited");
    }

}
Run Code Online (Sandbox Code Playgroud)

而且我担心......这是输出......

OnRender Entered
OnRender Exited
OnRenderSizeChanged Entered
OnRenderSizeChanged Exited
Run Code Online (Sandbox Code Playgroud)

那我在这里错过了什么?

更重要的是,如何在布局子系统完成其工作后获取ActualWidthActualHeight值,但在渲染控件之前,我可以在OnRender覆盖中需要之前创建几何体?

我最近实施覆盖ArrangeOverride做为所传递的还有包含什么大小值ActualWidthActualHeight应该是核心布局系统考虑到以后HorizontalAlignmentVerticalAlignment与"全屏"的值,最小值和最大值等,但他们实际上是依赖于从该覆盖返回的值,因此它比这复杂一点.

无论哪种方式,我仍然想知道为什么OnRenderSizeChanged呼叫不会发生时应该发生.思考?

标记

Cod*_*ked 6

一般来说,您应该能够从ArrangeOverride获得正确的大小。这不包括保证金之类的东西,但这可能不应该被考虑在内。您可以使用作为参数传递的大小作为“渲染”大小,也可以使用 base.ArrangeOverride 调用的返回值。

编辑:

在最终调用 OnArrangeOverride 之后,从排列方法调用 OnRender 方法。另一方面,OnRenderSizeChanged 是从 UpdateLayout 调用的,它被有效地分派为可视化树的给定部分一次全部执行。这就是在 OnRender 之后调用 OnRenderSizeChanged 的​​原因。

文档可能将“渲染”称为实际渲染到屏幕,而不是在调用 OnRender 时。WPF 可以缓存给定元素的渲染指令,并在需要时执行它们。因此,在 OnRenderSizeChanged 之前调用 OnRender 的事实并不意味着当时将实际的渲染指令提交给屏幕。

您可以修改您的 OnRenderSizeChanged 以强制再次调用 OnRender 使用:

protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
{
    Console.WriteLine("OnRenderSizeChanged Entered");

    base.OnRenderSizeChanged(sizeInfo);
    this.InvalidateVisual();

    Console.WriteLine("OnRenderSizeChanged Exited");
}
Run Code Online (Sandbox Code Playgroud)

如果 RenderSize 为“0,0”,您可能还想跳过 OnRender 代码。