我正在Decorator子类中进行自定义渲染。我们的渲染需要创建复杂的几何图形,只有当实际渲染的尺寸发生变化时,才需要重新创建它们。这样,我将几何图形创建移到了自己的函数UpdateGeometry
中,该函数创建,然后卡住该几何图形以供OnRender
使用。仅在响应ActualWidth
或ActualHeight
的更改时才需要调用此新函数。
更好的是,看来我们应该能够简单地重写OnRenderSizeChanged
,根据文档说明,该信息...
但是,无论我使用替代还是监听ActualWidth
和ActualHeight
的属性更改通知,我的日志记录始终显示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
那我在这里想念什么?
更重要的是,在布局子系统完成其工作之后,但在呈现控件之前,如何获得
ActualWidth
和ActualHeight
值,以便可以在OnRender
覆盖中需要它之前创建几何?我的最新实现重写了
ArrangeOverride
,因为传入的值的大小包含在核心布局系统考虑ActualWidth
和ActualHeight
且值为“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代码。