Don Kirkby
Don Kirkby

Reputation: 56590

Load a form without showing it

Short version: I want to trigger the Form_Load() event without making the form visible. This doesn't work because Show() ignores the current value of the Visible property:

tasksForm.Visible = false;
tasksForm.Show();

Long version: I have a WinForms application with two forms: main and tasks. The main form is always displayed. The user can either click a button to open the tasks form, or click some buttons that just run a task directly without opening the tasks form.

When a user asks to run a task directly, I'd like to just call some public methods on the tasks form without showing it. Unfortunately, the task logic depends on stuff that happens in the Form_Load() event. The only way I can find to trigger Form_Load() is to call Show(). The best I've been able to do is to show the form in the minimized state:

tasksForm.WindowState = FormWindowState.Minimized;
tasksForm.Show();

I suppose the cleanest solution would be to pull the tasks logic out of the tasks form and into a controller class. Then I can use that class from the main form and from the tasks form, and only load the tasks form when I need it visible for the user. However, if it's an easy thing to load the form without displaying it, that would be a smaller change.

Upvotes: 11

Views: 23651

Answers (8)

Sodoshi
Sodoshi

Reputation: 141

None of the answers solved the original question, so, add the below, call .Show() to load the form without showing it, then call .ShowForm() to allow it to be visible if you want to after:

private volatile bool _formVisible;
protected override void SetVisibleCore(bool value)
{
    base.SetVisibleCore(_formVisible);
}
public void ShowForm()
{
    _formVisible = true;
    if (InvokeRequired)
    {
        Invoke((Action) Show);
    }
    else
    {
        Show();
    }
}

Upvotes: 0

Ben Glancy
Ben Glancy

Reputation: 11

Sometimes this would be useful without it being bad design. Sometimes it could be the start of a migration from native to managed.

If you were migrating a c++ app to .NET for example, you may simply make yourwhole app a child window of the .NET form or panel, and gradually migrate over to the .NET by getting rid of your c++ app menu, status bar, toolbar and mapping teh .NEt ones to your app using platform invoke etc...

Your C++ app may take a while to load, but the .NET form doesn't..in which you may like to hide the .NEt form until your c++ app has initialised itself.

I'd set opacity=0 and visible=false to false after calling show, then when your c++ app loads, then reverse.

Upvotes: 1

Jeff Roe
Jeff Roe

Reputation: 3206

Perhaps it should be noted here that you can cause the form's window to be created without showing the form. I think there could be legitimate situations for wanting to do this.

Anyway, good design or not, you can do that like this:

MyForm f = new MyForm();
IntPtr dummy = f.Handle; // forces the form Control to be created

I don't think this will cause Form_Load() to be called, but you will be able to call f.Invoke() at this point (which is what I was trying to do when I stumbled upon this SO question).

Upvotes: 20

configurator
configurator

Reputation: 41616

From MSDN:

Form.Load
Occurs before a form is displayed for the first time.

Meaning the only thing that would cause the form to load, is when it is displayed.
Form.Show(); and Form.Visible = true; are the exact same thing. Basically, behind the scenes, Show checks for various conditions, then sets Visible to true. So obviously, setting visible to false (which it already is) before showing the form is meaningless.

But let's forget the technicalities. I completely agree with Rich B and Shaun Austin - the logic shouldn't be in that form anyway.

Upvotes: 5

Shaun Austin
Shaun Austin

Reputation: 3842

I totally agree with Rich B, you need to look at where you are placing your application logic rather than trying to cludge the WinForms mechanisms. All of those operations and data that your Tasks form is exposing should really be in a separate class say some kind of Application Controller or something held by your main form and then used by your tasks form to read and display data when needed but doesn't need a form to be instantiated to exist.

It probably seems a pain to rework it, but you'll be improving the structure of the app and making it more maintainable etc.

Upvotes: 6

McKenzieG1
McKenzieG1

Reputation: 14179

Move mandatory initialization code for the form class out of the Load event handler into the constructor. For a Form class, instantiation of an instance (via the constructor), form loading and form visibility are three different things, and don't need to happen at the same time (although they do obviously need to happen in that order).

Upvotes: 0

Sam
Sam

Reputation: 2201

If you make the method public, then you could access it directly.... however, there could be some unexpected side effects when you call it. But making it public and calling it directly will not draw the screen or open the form.

Upvotes: 0

GEOCHET
GEOCHET

Reputation: 21313

It sounds to me like you need to sit down and re-think your approach here. I cannot imagine a single reason your public methods need to be in a form if you are not going to show it. Just make a new class.

Upvotes: 8

Related Questions