Mar*_*eIV 7 wpf layout rendering resize render
我在Decorator子类中进行自定义渲染.我们的渲染需要创建复杂的几何体,只有当实际渲染的尺寸发生变化时才会重新创建.因此,我已将几何创建移动到其自己的函数中UpdateGeometry,该函数创建,然后冻结几何体以供使用OnRender.只需要响应ActualWidthor中的更改来调用此新函数ActualHeight.
更好的是,看起来我们应该能够简单地覆盖OnRenderSizeChanged,根据文档说明......
"在派生类中重写时,参与由布局系统指导的渲染操作.在布局更新之后和渲染之前,如果元素的RenderSize由于布局更新而发生更改,则调用此方法."
但是,如果不管我使用的覆盖或听的属性更改通知ActualWidth和ActualHeight,我的记录一致表明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)
那我在这里错过了什么?
更重要的是,如何在布局子系统完成其工作后获取ActualWidth和ActualHeight值,但在渲染控件之前,我可以在OnRender覆盖中需要之前创建几何体?
我最近实施覆盖ArrangeOverride做为所传递的还有包含什么大小值ActualWidth和ActualHeight值应该是核心布局系统考虑到以后HorizontalAlignment和VerticalAlignment与"全屏"的值,最小值和最大值等,但他们实际上是依赖于从该覆盖返回的值,因此它比这复杂一点.
无论哪种方式,我仍然想知道为什么OnRenderSizeChanged呼叫不会发生时应该发生.思考?
标记
一般来说,您应该能够从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 代码。