我正在Decorator子类中进行自定义渲染。我们的渲染需要创建复杂的几何图形,只有当实际渲染的尺寸发生变化时,才需要重新创建它们。这样,我将几何图形创建移到了自己的函数UpdateGeometry中,该函数创建,然后卡住该几何图形以供OnRender使用。仅在响应ActualWidthActualHeight的更改时才需要调用此新函数。

更好的是,看来我们应该能够简单地重写OnRenderSizeChanged,根据文档说明,该信息...



但是,无论我使用替代还是监听ActualWidthActualHeight的属性更改通知,我的日志记录始终显示OnRender首先发生!嗯...

为确保这不是我在代码中所做的事情,我创建了一个准系统测试装饰器子类,并在覆盖的入口和导出处添加了日志记录。这是整个类(class)...

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

}

正如我所担心的...这是输出...
OnRender Entered
OnRender Exited
OnRenderSizeChanged Entered
OnRenderSizeChanged Exited

那我在这里想念什么?

更重要的是,在布局子系统完成其工作之后,但在呈现控件之前,如何获得ActualWidthActualHeight值,以便可以在OnRender覆盖中需要它之前创建几何?

我的最新实现重写了ArrangeOverride,因为传入的值的大小包含在核心布局系统考虑ActualWidthActualHeight且值为“Stretch”,最小值和最大值等之后,应该为值。但是它们的实际含义取决于该覆盖返回的值,因此它要复杂得多。

无论哪种方式,我仍然想知道为什么HorizontalAlignment调用在应有的情况下没有发生。有什么想法吗?

标记

最佳答案

通常,您应该能够从ArrangeOverride获得正确的大小。这不包括“ margin ”之类的内容,但可能不应该考虑在内。您可以将作为参数传递的大小用作“渲染”大小,也可以使用base.ArrangeOverride调用的返回值。

编辑:

在最终调用OnArrangeOverride之后,从Arrange方法中调用OnRender方法。另一方面,从UpdateLayout调用OnRenderSizeChanged,对于视觉树的给定部分,可以有效地调度该OnRenderSizeChanged一次执行所有操作。这就是为什么在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");
}

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

10-06 04:10