Click here to Skip to main content
15,886,578 members
Articles / Programming Languages / C#
Article

Open Forms Elegantly

Rate me:
Please Sign up or sign in to vote.
3.27/5 (7 votes)
2 Nov 2008CPOL3 min read 25.3K   179   16   8
This article will show an elegant way to open a lot of forms, without the redundant code

Introduction

This article will introduce a way to reduce the code that is used to open various forms from an applications main menu.

The Problem

As with most Windows applications, the main form will mainly be used to open a lot of other different forms, depending on the application's purpose.

The usual way would be to handle the button's "Click" event, and to instantiate an instance of the form, and to "ShowDialog".

When the application needs to open a lot of forms, these "Click" events for each button could cause the code to become very messy quickly.

I therefore set out to try and find an easier way to reduce the code needed to open all the different forms.

In the sections below, I will explain the solution I came up with.

The Solution

Every component has a "Tag" property that takes an Object as value. This means that we can save any value we want in it.

For the proposed solution, we will make use of this Tag property to save the name of the form we want to open. For example, if we want a button to launch a form named "frmTest", we use the designer properties to set the Tag property to "frmTest". Take note: the name of the form is NOT the value in the "Text" property, it is the value in the "Name" property.

We have only ONE method that will take care of launching all the various forms.

The LaunchForm method is the method we link to the Click event of the button. This can easily be done with the designer properties. Because we need to link this method to the button's Click event, we need to specify the two parameters required. The parameters are:

  • sender of type object, which is the control that the Click event belongs to
  • e of type EventArgs, which is the event arguments associated with the Click event
C#
/// <summary>
/// Method is used to launch an instance of a desired Form. 
/// Link to the Click event of the objects.
/// </summary>
/// <param name="sender">Object used to launch the Form.</param>
/// <param name="e">Event arguments</param>
internal void LaunchForm(object sender, EventArgs e)
{
    //Set the default value to empty
    String FormName = String.Empty;
    try
    {
        //Cast the sender to the appropriate type
        ToolStripMenuItem item = sender as ToolStripMenuItem;

        //A form name consists of the namespace, as well as the type.
        //To get the namespace dynamically, we use a bit of reflection
        //Assembly.GetExecutingAssembly().FullName returns the fullname 
        //of this assembly.
        //We then use the Split function to obtain only the namespace
        //(The first part returned in the string array.
        //We then combine the returned namespace with the FormName
        //specified in the Tag property of the ToolStripMenuItem.
        FormName = Assembly.GetExecutingAssembly().FullName.Split(',')[0] +
        			"." + item.Tag.ToString(); ;

        //Use the string representation of the FormName to obtain the 
        //actual type to instantiate.
        Type uiType = Assembly.GetExecutingAssembly().GetType(FormName);

        using (Form form = Activator.CreateInstance(uiType) as Form)
        {
            //Now we have an instance of the form, 
            //and can modify the properties to suit our need
            form.StartPosition = FormStartPosition.CenterScreen;

            form.Text = "Demo - " + item.Text;

            //Set the Icon of the Form to that of the Image used on the MenuItem
            form.Icon = GetIconFromImage(item.Image);

            //Show the Form.
            form.ShowDialog();
        }
    }
    catch (Exception ex)
    {
        //Do some proper exception handling here
        MessageBox.Show(String.Format
        	("Error opening window: {0}. Error Message: {1}", FormName, ex.Message));
    }
}

A form's full name consists of the name of the form, as well as the namespace in which it resides.

If we look at the code, we can see that with a little bit of reflection we can easily obtain the namespace of the form, and by combining it with the name specified in the Tag property.

Once we have an instance of the Form we want, we are free to do all sorts of manipulations to the forms we want to launch. In the sample code above, we set the StartPosition. We also use the sender parameter to determine the type of control used to launch the form. By doing this, we can access the Text, as well as other properties such as the image, etc….

By launching the forms in this way, the code is in one centralised location, which makes maintaining it very easy!

Below is a screenshot of which properties must be set. The screenshot is of a ToolStripMenuItem that opens a form called "frmTest". As you can see, the Tag property is set to "frmTest", and the Click event is set to call "LaunchForm". That's all you need!

Image of properties to set.

Please let me know what you think, and if you found this code useful! I welcome any feedback!

History

  • 31st October, 2008 - Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Inivit Systems
South Africa South Africa
I am currently employed by Inivit Systems. Here we strive to use cutting edge technologies, in order to provide our clients with the best possible software and continue to offer them a competitive edge.

We are responsible for all kinds of applications, ranging from web applications to desktop applications, including integration into some older legacy systems.

I love programming and solving puzzles, but beside that I enjoy experimenting with new technologies, reading, watching movies and relaxing with friends.

Comments and Discussions

 
GeneralWhile trying to open MDI child - Child opens and then closes immediately Pin
Tushar Bhatt5-Jan-09 23:10
Tushar Bhatt5-Jan-09 23:10 
GeneralPerhaps a better way to get the Namespace Pin
Ilíon7-Nov-08 1:20
Ilíon7-Nov-08 1:20 
GeneralLoading menu items in runtime Pin
beatles16923-Nov-08 23:20
beatles16923-Nov-08 23:20 
Hi
Thanks for your article.
What I'd like to suggest is a way of loading menu items at run time.I mean if there is no particular code for each menu item on your main form and they are all calling a single method then you can have a mechanism that create menu items at run time and bind all of them to that single method.
For example you can use a XML/config file to tell your application how to build the main menu for you.
Something like this:

<br />
<MenuItem id="mnuFile" name="&File"><br />
          <MenuItem id="mnuOpen" name="&Open" form="frmOpen" /><br />
</MenuItem><br />

This way every time you want to add a new form to your main form you don't have to change its code or even compile it (if the form you want to show it's not in the same assembly as your main form).
GeneralFeedback Pin
Dieter Deysel3-Nov-08 21:13
Dieter Deysel3-Nov-08 21:13 
Generalhmmm. Pin
johannesnestler3-Nov-08 3:57
johannesnestler3-Nov-08 3:57 
GeneralNot so nice, really Pin
juggler3-Nov-08 2:17
juggler3-Nov-08 2:17 
GeneralNice..But Pin
BAIJUMAX2-Nov-08 18:11
professionalBAIJUMAX2-Nov-08 18:11 
GeneralRe: Nice..But Pin
Itay Sagui2-Nov-08 21:49
Itay Sagui2-Nov-08 21:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.