Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine when the user control is fully loaded and shown?

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)

like image 369
username Avatar asked Jul 11 '11 15:07

username


2 Answers

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();
}
like image 125
Ben Voigt Avatar answered Oct 12 '22 01:10

Ben Voigt


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.

like image 38
DRapp Avatar answered Oct 12 '22 01:10

DRapp