wpf - 在WPF中,如何在控件实际呈现之前获取控件的呈现大小?

标签 wpf layout resize rendering render

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

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

"When overridden in a derived class, participates in rendering operations that are directed by the layout system. This method is invoked after layout update, and before rendering, if the element's RenderSize has changed as a result of layout update."



但是,无论我使用替代还是监听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代码。

关于wpf - 在WPF中,如何在控件实际呈现之前获取控件的呈现大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5652156/

相关文章:

c# - DataGrid 中的偏移行

c# - 使用 EventTrigger 引发附加事件

android - Galaxy Tab 10 布局限定符

ios - 使用 Swift 的 Core Graphics/Quartz Core resizing 从较小尺寸调整到较大尺寸

html - Div 不会自动调整另一个 div 内的高度

c# - WPF TextBox 滚动到结束只工作一次

c# - 为什么在设置 DataContext 时我的验证规则没有运行?

reactjs - 在 ReactJs 中为组件创建不同的移动布局

layout - 是否有示例布局可以使 doxygen 文档更具吸引力?

java - 如何更改 Akka 路由器的大小?