在WPF中,如何在控件实际渲染之前获得其渲染大小?
我正在Decorator子类中进行自定义渲染。我们的渲染需要创建复杂的几何体,只有在实际渲染大小更改时才需要重新创建这些几何体。因此,我将几何体创建移到了自己的名为在WPF中,如何在控件实际渲染之前获得其渲染大小?,wpf,layout,resize,rendering,render,Wpf,Layout,Resize,Rendering,Render,我正在Decorator子类中进行自定义渲染。我们的渲染需要创建复杂的几何体,只有在实际渲染大小更改时才需要重新创建这些几何体。因此,我将几何体创建移到了自己的名为UpdateGeometry的函数中,该函数创建几何体,然后冻结几何体,以便在OnRender中使用。此新函数只需在响应实际宽度或实际高度的更改时调用 更好的是,看起来我们应该能够简单地覆盖onrenderizechanged,根据文档状态 “在派生类中重写时, 参与渲染操作 由布局指示的 系统。此方法在 布局更新,在渲染之前, 如果
UpdateGeometry
的函数中,该函数创建几何体,然后冻结几何体,以便在OnRender
中使用。此新函数只需在响应实际宽度
或实际高度
的更改时调用
更好的是,看起来我们应该能够简单地覆盖onrenderizechanged
,根据文档状态
“在派生类中重写时,
参与渲染操作
由布局指示的
系统。此方法在
布局更新,在渲染之前,
如果元素的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
那么我在这里错过了什么
更重要的是,在布局子系统完成其工作后,但在渲染控件之前,如何获取实际宽度
和实际高度
值,以便在OnRender
覆盖中需要几何体之前创建几何体
我的最新实现覆盖了ArrangeOverride
,因为传入的值有一个包含实际宽度
和实际高度
值的大小,在核心布局系统考虑水平对齐
和垂直对齐
后,这些值应该是值“拉伸”的值、最小值和最大值等,但它们的实际值取决于覆盖返回的值,所以比这要复杂一些
不管怎样,我仍然想知道为什么OnRenderSizeChanged
调用在应该发生的时候没有发生。想法
标记通常,您应该能够从中获得正确的大小。这不包括像保证金这样的东西,但这可能不应该被考虑在内。可以使用作为参数传递的大小作为“渲染”大小,也可以使用base.ArrangeOverride调用的返回值
编辑:
最终调用OnArrangeOverride后,将从Arrange方法调用OnRender方法。另一方面,OnRenderSizeChanged是从UpdateLayout调用的,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代码。。。这就是我刚才在上面描述的底部编辑的内容,我们目前正在做的“变通”,但这仍然不能解释OnRenderSizeChanged覆盖没有按照文档所说的那样工作。另外,我认为唯一没有考虑的是边距,因为这超出了渲染的范围。你知道还有什么事情没有考虑到吗?@marquev-根据你的评论更新了我的答案。看来我需要做的就是坚持使用ArrangeOverride。你知道答案了!:)