如何“插入” WPF 渲染周期从 VisualTreeHelper 获得准确的结果?

发布于 2024-08-09 12:45:26 字数 478 浏览 4 评论 0原文

我目前正在编写一个 WPF 用户控件 (PARENT),它可以包含多个子 (CHILD) 用户控件。我正在将(子)控件与折线连接。

为此,我需要 CHILD 用户控件的位置。 但是,我从 VisualTreeHelper.GetOffset 获得的位置为零。 WPF 可能尚未完成调整子控件的大小并将其放置在内存中,因为当我将代码放入控件的 OnLoaded 事件处理程序中时,我确实获得了子控件的正确位置。

这是一个问题,因为即使在加载我的父控件之后,我仍然希望能够添加子控件并更新我的行。

我目前解决此问题的方法是重写子控件的 OnRender 并为主控件引发一个事件,以便它知道可以使用 VisualTreeHelper 来获取正确的值。

然而,这意味着我需要重新绘制线条,直到最后一个 CHILD 控件完成渲染。

我当前的解决方案感觉更像是一种解决方法,而不是解决方案。如何“插入”WPF 渲染周期以从 VisualTreeHelper 获得准确的结果?

I am currently writing a WPF User control (PARENT) which can contain multiple child (CHILD) user controls. I am connecting the (CHILD) controls with polylines.

To do this I need the locations of the CHILD user controls.
However, the locations i get from VisualTreeHelper.GetOffset are zero. WPF is probably not finished yet with sizing and placing the CHILD controls in memory, because when I put my code in the OnLoaded event handler of my control I do get correct locations for my child controls.

This is a problem because even after I loaded my PARENT control I still want to be able to add CHILD controls and update my lines.

How I have currently solved this is by overriding the OnRender of my CHILD controls and raising an event for my MAIN control so it knows it can use the VisualTreeHelper to obtain correct values.

This however means that I will need to redraw my lines untill the last CHILD control has finished rendering.

My current solution feels more like a workaround than a solution. How can you "plug into" the WPF rendercycle to get accurate results from VisualTreeHelper?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

第七度阳光i 2024-08-16 12:45:26

尝试重写父控件上的 ArrangeOverride 或 OnRender。 WPF 执行三阶段布局/渲染过程:首先,它询问控件需要多少空间(测量),然后告诉控件它们实际上为收到的所有请求提供了多少空间(排列),然后它实际上绘制每个控件指定的区域内的所有内容(渲染)。为此,它遵循可视化树 - 根元素(例如,窗口)被告知进行测量;它必须要求它的孩子们进行测量,孩子们必须要求他们的孩子们等等,一直到叶元素,然后整个事情开始一路返回到根。然后它开始排列通道,最后是渲染通道。

通过观察子级的 OnRender,您就隐含地表示您希望在测量和排列发生之后、但在父级开始绘制自身之前开始绘制。这可以等效于父级的 OnRender - 它包装了子级的 OnRender。您也可以在父级的 ArrangeOverride 中执行此操作,它包装子级的排列过程,这是 (IIRC) VisualTreeHelper.GetOffset() 访问的值实际设置的位置。

最后,通过查看父控件,您隐式地等待所有子控件完成排列/渲染 - 这意味着您不必费力地尝试找出最后一个子控件何时完成渲染。

Try overriding ArrangeOverride or OnRender on the parent control. WPF does a three-stage layout/render pass: first, it asks the controls how much space they need (measure), then it tells the controls how much space they actually have given all of the requests received (arrange), and then it actually draws everything inside the regions each control was given (render). For this to work, it follows the visual tree - the root element (say, Window) is told to measure; it has to ask its children to measure, who have to ask their children, etc. all the way down to the leaf elements before the whole thing starts returning all the way back to the root. Then it starts the arrange pass, and finally the render pass.

By watching the children's OnRender, you're implicitly saying that you want to start drawing after measure and arrange have occurred, but before the parent starts drawing itself. This can be made equivalent to the parent's OnRender - which wraps the children's OnRenders. You might also be able to do this in the parent's ArrangeOverride, which wraps the children's arrange pass, which is where (IIRC) the values VisualTreeHelper.GetOffset() accesses actually get set.

Finally, by looking at the parent control, you're implicitly waiting for all the child controls to finish arranging/rendering - which means that you won't have to monkey around trying to figure out when the last child has finished rendering.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文