Caster Troy
Caster Troy

Reputation: 2866

How can I wait Until a Form Handle Has Been Created Before Using Its' Components?

I am dynamically instantiating a Form. I cannot interact with the components (such as a TextBox) on the Form until the handle has been created (else, an exception will be thrown).

Currently I block the thread using a while loop:

public void OutputDesktopFrame(MessagingService service, DesktopFrame desktopFrame)
{
    IRemoteDesktopView view = GetView(service);
    view.UpdateFrame(desktopFrame);
}

private IRemoteDesktopView GetView(MessagingService service)
{
    T view;
    bool viewExists = _views.TryGetValue(service, out view);

    if (viewExists == false)
    {
        view = CreateAndShowView(service);
    }

    return view;
}

private T CreateAndShowView(MessagingService service)
{
    T remoteDesktopView = new T();

    _views.Add(service, remoteDesktopView);

    Thread pumpThread = new Thread(() => remoteDesktopView.ShowDialog());
    pumpThread.Start();


    while (remoteDesktopView.IsHandleCreated == false)
    {
        //Do not return until the handle has been created!
    }

    return remoteDesktopView;
}

I do not like this mechanism. I am looking for an elegant solution.

Please take into account that I am coding against an interface. I thought about using a ManualResetEvent or something of the like but having to implement and handle the ManualResetEvent within each Form that implements the interface doesn't sound appealing to me. If you don't agree with me. that's just fine. I merely suspect my current solutions are not the most elegant.

Upvotes: 2

Views: 6531

Answers (2)

Treb
Treb

Reputation: 20281

You have to wait for the handle to be created somehow. So you will end up with something like while (form.IsHandleCreated == false) { ... } somewhere in your code. The only question is where to put it.

If you do it like in your example above, you need to code the while loop every time you create a form If you choose the alternative you mentioned, using an event raised by the form, you need to implement it in each form (and create an event handler and hook it up).

I don't know if CreateAndShowForm() is a framework method, or something you can change yourself. If you can change it, that's where I would put the waiting. That way you only need to code it once.

Another approach to avoid the code duplication would be handling it in the form, implementing it in your own abstract form base class, and deriving you actual forms from that class. In my opinion, that is complete overkill for this issue - way too much work for very little gain.

If you can't change CreateAndShowForm(), I recommend going with the example above - yes, it definitely isn't elegant, but it gets the work done, the source code is easy to understand, and it doesn't require the additional work of event handling.

Upvotes: 2

King King
King King

Reputation: 63327

You can add code to a HandleCreated event handler like this:

private void Form1_HandleCreated(object sender, EventArgs e){
   //your code
}

The event is not listed in Properties window, you have to register the event handler using code:

HandleCreated += Form1_HandleCreated;

Upvotes: 7

Related Questions