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

时间:2011-07-11 15:54:57

标签: c# winforms events user-controls load

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

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

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

修改

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

3 个答案:

答案 0 :(得分:6)

为了使用户界面更具响应性,你应该给自己发一条消息(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();
}

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

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

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