我在Decorator子类中进行自定义渲染。我们的渲染需要创建复杂的几何体,只有在实际渲染的尺寸发生变化时才会重新创建。因此,我已将几何创建移动到其自己的名为UpdateGeometry
的函数中,该函数创建,然后冻结几何体以在OnRender
中使用。只需响应ActualWidth
或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");
}
}
正如我所担心的......这是输出......
OnRender Entered
OnRender Exited
OnRenderSizeChanged Entered
OnRenderSizeChanged Exited
那我在这里错过了什么?
更重要的是,如何在布局子系统完成其工作后获取ActualWidth
和ActualHeight
值,但是在渲染控件之前,我可以在{}中需要之前创建几何体{1}}覆盖?
我的最新实施会覆盖OnRender
,因为其中传递的值的大小包含ArrangeOverride
和ActualWidth
值 应该 在核心布局系统考虑ActualHeight
和HorizontalAlignment
后,其值为“拉伸”,最小值和最大值等,但它们实际上取决于从该覆盖返回的值,所以它比那复杂一点。
无论哪种方式,我仍然想知道为什么VerticalAlignment
调用不应该发生。想法?
标记
答案 0 :(得分:4)
通常,您应该能够从ArrangeOverride获得正确的尺寸。这不包括保证金等内容,但可能不应该考虑到这一点。您可以使用作为参数传递的大小作为“渲染”大小,也可以使用base.ArrangeOverride调用的返回值。
编辑:
在最终调用OnArrangeOverride之后,从Arrange方法调用OnRender方法。另一方面,OnRenderSizeChanged是从UpdateLayout调用的,有效地调度它以便对可视树的给定部分一次性执行。这就是在OnRender之后调用OnRenderSizeChanged的原因。
文档可能会将“渲染”称为实际呈现给屏幕,而不是在调用OnRender时。 WPF可以缓存给定元素的呈现指令,并在需要时执行它们。因此OnRender在OnRenderSizeChanged之前调用的事实并不意味着当时它的实际渲染指令已提交到屏幕。
您可以修改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代码。