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

本文关键字:加载 显示 何时完 何确定 用户 控件 | 更新日期: 2023-09-27 18:01:41

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

我有一个由几个选项卡页组成的应用程序。在其中一个上,我一次加载了几十个用户控件的列表。目前我正在做它在加载事件,因为我有一个小延迟之前,这个页面被加载。我想做的是让UI响应更灵敏,并在页面完全加载后填充列表。是否有任何方法来跟踪何时用户控件已完全加载它的内容?

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

编辑

让它更清楚。我在页面容器上有一些子控件,并且我有一个稍后尝试加载的自定义控件列表。下面几个答案中描述的两种方法的问题是,当我开始加载控件时,他们不让容器上的其他子控件显示,这就是为什么我有那些丑陋的效果(我正在使用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线程上执行这个加载将总是使表单无响应,无论你在什么事件中执行它-将此更改为在表单加载后完成,那么它只会使表单无响应和可见,而不是在表单显示之前引起延迟。

如果没有办法加速列表的加载,那么你可能需要改变你的表单加载逻辑,这样"繁重的工作"就会在后台线程中完成,这样当列表被填充时,表单仍然是响应的。您应该意识到,多线程代码更难以理解,如果执行不当,可能会产生间歇性且难以调试的bug,因此您应该首先尝试提高现有代码的速度。也就是说,如果你不能加快列表加载速度,并且延迟是不可接受的,那么就没有其他选择了。

如果你选择异步加载你的列表(在后台线程中),那么这个想法是启动一个后台线程(通常通过BackgroundWorker)来准备一个要添加的项目列表——当这个完成(或失败)时,表单/列表框将更新提供的项目列表。

你应该能够在互联网上找到大量关于如何做到这一点的资源,这些资源将更详细地涵盖这一点。