Monday, March 31, 2008

System.Windows.Forms.Form.Owner

Although this little chestnut has been in the CF since 2.0 (Nov 2005) I'd thought I'd mention it here as some people still don't know about it.

If you've written Windows applications for the desktop you'd probebly used this property. On devices what you used to have to do was to write a 'hack' something similar to the following when calling sub-forms from within your application:
using (Form1 form1 = new Form1())
{
this.Text = "";
string str = this.Text;
form1.ShowDialog();
this.Text = str;
}
NativeMethods.SetForegroundWindow(hwnd);
Quite ugly huh! You had to set the Text property for the form to blank before calling a sub-form so that you wouldn't get two entries visible in the memory applet under Settings. P/Invoking SetForegroundWindow was also required to ensure your app would come back to the foreground after closing the sub-form if you had viewed other windows during the lifecycle of the sub-form.

Now all you have to code is the following:
using (Form1 form1 = new Form1())
{
form1.Owner = this;
form1.ShowDialog();
}
Lovely!

8 comments:

Christopher Fairbairn said...

Your code snippet also raises another interesting and (in my opinion) somewhat under used feature. That of the using statement and form instances.

I wonder what portion of System.Windows.Forms based applications actually dispose forms explictly instead of leaving it up to the garbage collector.

My guess is only a small percentage based upon the amount of code samples I've seen that look like the following:

Form1 form1 = new Form1();
form1.Owner = this;
form1.ShowDialog();

I perfer to do things explictly if given the option so try to use the using statement but this can lead to questions during code reviews etc as it is "different" from what some people expect.

Simon Hart said...

I agree and an interesting point, the using statement is under used. It promotes cleaner code, and I'm very fond of clean code, as we all are ;) It is amazing how many code samples out there do not make use of this little feature defined in the language specs.

A snippet from the C# spec:

"An alternative to using destructors is to let a class implement the System.IDisposable interface. This allows the client of the object to determine when to release the resources of the object, typically by accessing the object as a resource in a using statement (§8.13)."

This can be found under section: 3.9 Automatic memory management

The latest spec can be found here: http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc

Wingot said...

Your code:

form1.Owner = this;
form1.ShowDialog();

From what I can gather, the following gives the same result:

form1.ShowDialog(this);

Passing in the base form as an argument to the constructor, from what I can gather, set the Owner property to the base form.

Simon Hart said...

wingot: This is a Windows Mobile blog (Compact Framework) to which there is only one ShowDialog method that accepts no IWin32Window. You could however override the Form class yourself and implement this inline with the desktop version.

--
Simon.

monxalo said...

@Simon Hart:
an easy way to add more methods to existing types without creating a new derived type is to use Extensions (like LINQ).

An easy example for Wingot's suggestion:

public static class MyExtensions
{
public static Form ShowDialog(this Form form)
{
this.Owner = form;
this.ShowDialog();
}
}

Now you can use Form.ShowDialog(Form form)

:)

Reference:
http://msdn.microsoft.com/en-us/library/bb383977.aspx

monxalo said...

(Sorry, this is the correct code. Please copy and paste on my previous comment, thanks)

public class MyExtension
{
public static DialogResult ShowDialog(this Form owner, Form form)
{
form.Owner = owner;
return form.ShowDialog();
}
}

Simon Hart said...

@monxalo:

That is a a really cool idea. I'll do that and post the code.

Cheers
Simon.

Sebastian said...

Hey Simon,

have you tried your method with a simple Form.Show()? I'm getting indifferent results when opening the new form with a click or a button_down event: button_down the new form shows correctly with the focus changing to the new form.
With a click event, however, the focus remains with the owner form and only part of the new form shows (menu and title bar are still from the owner form).

Regards,

Sebastian