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

发布于 2024-11-19 23:55:17 字数 460 浏览 1 评论 0原文

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

我有一个由多个选项卡页面组成的应用程序。在其中一个上,我一次加载几十个用户控件的列表。目前我正在加载事件中执行此操作,因此在加载此页面之前我有一个小的延迟。我想做的是让 UI 更具响应性并在页面完全加载后填充列表。有什么方法可以跟踪用户控件何时完全加载其内容?

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

编辑

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

There were already a few similar questions on stackoverflow, but I haven't found the answer

I have an application that consists of several tab pages. On one of them I'm loading a list of a few dozen user controls at a time. Currently I'm doing it in Load event and because of that I have a small delay before this page is loaded. What I want to do is to make UI more responsive and fill the list after the page is fully loaded. Is there any way to track when the user control has fully loaded it's content?

VisibleChanged doesn't help too, because it fires before any other child control is shown. That causes some ugly visual effects when some of the child controls are still not visible when I'm starting to load control list.

EDIT

To make it more clear. I have some child controls on a page container and I have a list of custom controls I'm trying to load later. The problem with two approaches described in several answers below is that when I'm starting to load controls they do not let other child controls on the container to be shown and that is why I have those ugly effects (and I'm doing that with BackgroundWorker, but anyway it has to interact with the main thread to add controls to the list)

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

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

发布评论

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

评论(3

赏烟花じ飞满天 2024-11-26 23:55:17

为了使 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();
}

In order to make the UI more responsive, you should post yourself a message (Control.BeginInvoke), do one operation, post yourself another message. Then every time you do anything, the next step will get queued after all user messages, so user actions will get processed promptly.

One really nifty approach is to use yield return and let the compiler take care of all the closures logic:

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();
}
心房的律动 2024-11-26 23:55:17

看看 我的解决方案提供给另一个。他们有一个非常相似的问题。等到所有内容都完成加载后再执行某个操作,但并非每次表单都必须“激活”或“显示”。它涉及附加到您感兴趣的最外层控件的加载处理程序。在您的情况下,是选项卡式页面,但我提供的示例解决方案是在 FORM 级别。

Take a look at my solution offered to another. They had a very similar issue. Wait until EVERYTHING finished its loading before doing a certain action, but not every time a form necessarily became "activated" or "shown". It involves attaching to the Load handler of your outermost control of interest. In your case, the tabbed page, but the example solution I provided was at the FORM level.

乜一 2024-11-26 23:55:17

如果此列表的加载会产生轻微延迟,则在 UI 线程上执行此加载将始终使表单无响应,无论您在什么事件中执行此操作 - 将其更改为在表单加载后完成那么它只会使表单无响应且可见,而不是在显示表单之前造成延迟。

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

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

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

If the loading of this list incurs a small delay then doing this load on the UI thread will always make the form unresponsive no matter what event you do it in - changing this to be done after the form has loaded then it will just make the form unresponsive and visible as opposed to just causing a delay before the form is shown.

If there is no way to speed up the loading of the list then you will probably need to change your form loading logic so that the "heavy lifting" is instead done in a background thread so that the form remains responsive while the list is being populated. You should be aware that multithreaded code is more difficult to understand and when done incorrectly can produce bugs that are intermittant and difficult to debug and so you should definitely try to speed up your existing code first. That said if you can't speed up your list loading and the delay is unacceptable then there is not really any alternative.

If you do choose to load your list asynchronously (in a background thread) then the idea is to start a background thread (usually via a BackgroundWorker ) that does the hard work of preparing a list of items to be added - when this has finished (or failed) the form / list box is updated with the supplied list of items.

You should be able to find plenty of resources on how to do this on the internet that will cover this in more detail.

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