如何确定用户控件何时完全加载并显示?

stackoverflow上已经有一些类似的问题,但我还没有找到答案

我有一个由几个标签页组成的应用程序。 其中一个我一次只加载了几十个用户控件的列表。 目前我在Load事件中这样做,因为我在加载此页面之前有一点延迟。 我想要做的是使UI更具响应性,并在页面完全加载后填充列表。 有没有办法跟踪用户控件何时完全加载它的内容?

VisibleChanged也没有帮助,因为它会在显示任何其他子控件之前触发。 当我开始加载控制列表时,当某些子控件仍然不可见时,这会导致一些丑陋的视觉效果。

编辑

为了使它更清楚。 我在页面容器上有一些子控件,我有一个我想要稍后加载的自定义控件列表。 以下几个答案中描述的两种方法的问题是,当我开始加载控件时,他们不会让容器上的其他子控件显示出来,这就是为什么我会有那些丑陋的效果(我正在这样做BackgroundWorker,但无论如何它必须与主线程交互以向列表添加控件)

为了使UI更具响应性,你应该给自己发一条消息( Control.BeginInvoke ),做一个操作,给自己发一条消息。 然后,每当您执行任何操作时,下一步将在所有用户消息之后排队,因此将立即处理用户操作。

一个非常好的方法是使用yield return并让编译器处理所有闭包逻辑:

 IEnumerable AsyncLoadUI() { var p = new Panel(); Controls.Add(p); yield return null; for( int i = 0; i < 50; ++i ) { var txt = new TextBox(); p.Controls.Add(txt); yield return null; } } override void OnLoad(EventArgs e) { IEnumerator tasks = AsyncLoadUI().GetEnumerator(); MethodInvoker msg = null; msg = delegate { if (tasks.MoveNext()) BeginInvoke(msg); }; msg(); } 

看看我提供给另一个人的解决方案 。 他们有一个非常相似的问题。 等到一切完成加载后再做某个动作,但不是每次表格都必须“激活”或“显示”。 它涉及附加到您感兴趣的最外层控件的Load处理程序。 在您的情况下,标签页,但我提供的示例解决方案是在FORM级别。

如果加载此列表会产生一个小延迟,那么在UI线程上执行此加载将始终使表单无响应,无论您执行什么操作 – 更改此操作在表单加载后完成然后它将只是使表单没有反应和可见,而不是在显示表单之前导致延迟。

如果无法加速列表的加载,那么您可能需要更改表单加载逻辑,以便在后台线程中完成“繁重”,以便在填充列表时表单保持响应。 您应该知道multithreading代码更难以理解,如果不正确,可能会产生间歇性且难以调试的错误,因此您应该首先尝试加速现有代码。 那说如果你不能加快你的列表加载,并且延迟是不可接受的,那么实际上没有任何替代方案。

如果你确实选择异步加载列表(在后台线程中),那么我们的想法是启动一个后台线程(通常是通过BackgroundWorker )来完成准备要添加的项目列表的艰苦工作 – 当它完成时(或失败)使用提供的项目列表更新表单/列表框。

您应该能够在互联网上找到有关如何执行此操作的大量资源,以便更详细地介绍这一点。