Windows Application Development Using .Net and Windows Forms

This guide will give you an introduction to Windows Application Development using Visual Studio and C# and the basics of win form design.

6,584 words, estimated reading time 26 minutes.
Introduction to Programming with C#

This article is part of a series of articles. Please use the links below to navigate between the articles.

  1. Learn to Program in C# - Full Introduction to Programming Course
  2. Introdution to Programming - C# Programming Fundamentals
  3. Introduction to Object Oriented Programming for Beginners
  4. Introduction to C# Object-Oriented Programming Part 2
  5. Application Flow Control and Control Structures in C#
  6. Guide to C# Data Types, Variables and Object Casting
  7. C# Collection Types (Array,List,Dictionary,HashTable and More)
  8. C# Operators: Arithmetic, Comparison, Logical and more
  9. Using Entity Framework & ADO.Net Data in C# 7
  10. What is LINQ? The .NET Language Integrated Query
  11. Error and Exception Handling in C#
  12. Advanced C# Programming Topics
  13. All About Reflection in C# To Read Metadata and Find Assemblies
  14. What Are ASP.Net WebForms
  15. Introduction to ASP.Net MVC Web Applications and C#
  16. Windows Application Development Using .Net and Windows Forms
  17. Assemblies and the Global Assembly Cache in C#
  18. Working with Resources Files, Culture & Regions in .Net
  19. The Ultimate Guide to Regular Expressions: Everything You Need to Know
  20. Introduction to XML and XmlDocument with C#
  21. Complete Guide to File Handling in C# - Reading and Writing Files

This guide will give you an introduction to Windows Forms Application development using Visual Studio and C# and the basics of form design.

Controls such as text boxes, buttons, checkboxes and so on, can all be added to a form by dragging and dropping from the toolbox to the form. The editor will also allow you to align multiple controls and will show you the recommended distance between controls.

When you create a new Windows Application project in Visual Studio or Visual C# Express, you are presented with a blank form in design mode. You can resize the form using the draggable corner markers and you can drag controls to the form by dragging and dropping them from the toolbox to the form.

The main areas of the Integrated Development Environment (IDE) that will be used are the form designer, code designer, control toolbox, solution explorer and properties window. If these panels or windows are not visible in your IDE, you can access them from within the View menu. They can be set to fold away when not in use to create more design/code space and appear when you hover over the tab, or they can be 'pinned' with the pushpin icon and they will stay open in their current position.

Visual Basic Form Design
Visual Basic Form Design

Have a play with dragging components onto the form from the toolbox and add a text box. Now add a button to the form and drag it around. Notice how the editor will provide alignment markers, and how it will 'snap' to the recommended position next to the textbox.

It is very highly recommended, as well as good practice, to name all components and forms properly and meaningfully. When you have a complex form, it is difficult to differentiate between Button1, Button2, Button3, TextBox1, TextBox2, TextBox3 and so on when you are coding. It is much better to give these components proper names to avoid confusion.

The recommendation is to use a three-letter prefix (lowercase) for the type of control (e.g. btn for Button, txt for TextBox, lbl for Label and so on) followed by a meaningful name (e.g. btnSubmitData, txtUsername or lblPasswordReminder). You should also rename the form to frmMain or an appropriate name for the function of the form.

You can rename components by changing the (Name) property in the properties window.

I have named the button btnShowMessage and the text box txtUserInput. You should also give the button a meaningful caption, so find the property called Title and type in "Show Message".

The most used feature of the ID is the properties and Events window. Events will be covered in more detail in a later tutorial, but for Windows Forms, an event is called when the user does something, e.g. Clicking a button, this will fire the Click event of the button. Events in Windows applications are automatically wired up, you do not have to do any special coding. Events can be automatically wired up in one of two ways. You can double-click a component, which will auto-wire the component's default event (The default button event is the Click event, Default form event is Load). The other method is to select the component and select events from the Properties window. This will list all the events associated with that control, to wire up an event simply double-click the event which will load up the code editor with the event wired up for you.

Visual C# Properties Window
Visual C# Properties Window

Let's continue our simple demo program, double click on the button and you will a new function in the code:

C#
private void btnShowMessage_Click(object sender, EventArgs e)
{

}

Into this function, we shall show a message box containing the data entered in the text box.

C#
MessageBox.Show(txtUserInput.Text);

When run, this will show a message box with the string entered into the text box.

Auto Code Generation

When you place a button or a textbox (or any other component) onto a form, an instance of an object is created for you. At the top of the code viewer, you may have noticed two dropdown boxes. These allow you to quickly navigate through your methods, events and classes. If you drop down the right-hand box, select the InitializeComponent method. This will take you to a hidden region in the code that contains the code added by Visual Studio. You should be able to locate two lines that create a text box and button.

C#
this.btnShowMessage = new System.Windows.Forms.Button();
this.txtUserInput = new System.Windows.Forms.TextBox();

Because we are creating an instance of classes defined by Microsoft, they all inherit certain methods and properties. All objects will have a ToString method, and all controls will have an ID and Name among other items. Input elements will have a Text or Value property, and all clickable items (Button, Checkbox, Radio button and so on) will have a click event. Default values are set up in the InitializeComponent method, you can add or modify these items.

A little lower down, you should be able to find a line that hooks up the click event to a click function, such as the one shown below.

C#
this.btnShowMessage.Click += new System.EventHandler(this.btnShowMessage_Click);

You do not have to worry about any of these automatically generated code sections and they have hidden away from you, but you should still be familiar with the concepts.

Now we are going to add another button under our existing button, named btnUpdateTextBox with the title of Update. Double-click on the button to add the event and enter the code below:

C#
txtUserInput.Text = "Hello World"

Now when you run the program, you can type some text into the box and press the first button to see a message dialogue with the contents of the text box and press the second to update the contents of the text box.

List Boxes and Tree Views in C#

Trees, Lists and Grids are all very good ways of presenting data to the user, and they each have their particular uses.

We have already seen list boxes briefly and now we will have a closer look at the list box and how to use it. All of these controls are data aware, that is they can be bound to a data source. We will have a look at Grids when we look at using data on Windows forms.

List Boxes and Combo Boxes

List boxes are used whenever you need to display a collection of items in a list format. If space is limited you can use a dropdown (combo) box instead. Both listBox and comboBox have the same methods for accessing the list items.

Adding and Removing Items

You can use the IDE interface to add items to a list, however, it is often required that we add items, or delete items, at runtime.

C#
ListBox.Items.Add("Text to Show");

The add method will add a new item to the bottom of the list. You can use the Insert method to add an item at a specific location on the list, 0 will add the item as the first item.

C#
ListBox.Items.Insert(5,"Text to Show");

Each item on a list box has an ItemIndex property to denote its position. The first item of the list has an ItemIndex of 0 (zero).

You can remove items from the list using the RemoveAt method, where you specify the index of the item to delete.

C#
ListBox.Items.RemoveAt(5);

You can clear a list of all items using Clear.

C#
ListBox.Items.Clear();

Accessing Items and Selections

You can access an individual item through the Items collection to read and write items.

C#
ListBox.Items[2] = "Hello World";
string myString = ListBox.Items[0];

Iterating through Items

There are two main methods for iterating through the items in the list, using a for and a for each loop.

C#
for (int i = 0; i < listBox.Items.Count - 1; i++)
{
  MessageBox.Show(listBox.Items[i].ToString());
}

Because the listBox component accepts elements of any type, you must specify the type within the foreach statement.

C#
foreach (string O in listBox.Items)
{
  MessageBox.Show(O);
}

In both cases the Items collection is read-only, so cannot be assigned to.

Tree Views

Tree views are an organised list view the same as the Windows Explorer folder list view. It separates a list into sections that have subsections and so on. Like list and combo views, items can be added to a TreeView using the inbuilt IDE designer, and they can be modified at runtime. Unlike lists where an element is called an Item, each element of the tree is known as a Node.

To add a simple node to a Treeview

C#
 TreeNode node = new TreeNode();
node.Name = "nodNewNode";
node.Text = "My New Node";

treeView1.Nodes.Add(node);

You can also add sub-nodes to a node or the tree view by creating a new TreeNode object for each item.

List Boxes and Tree Views in C#
List Boxes and Tree Views in C#
C#
TreeNode node = new TreeNode();
node.Name = "nodNewNode";
node.Text = "My New Node";

TreeNode node2 = new TreeNode();
node2.Name = "nodNewNode2";
node2.Text = "My New Sub Node (a)";
node.Nodes.Add(node2);

TreeNode node3 = new TreeNode();
node3.Name = "nodNewNode2";
node3.Text = "My New Sub Node (b)";
node.Nodes.Add(node3);

treeView1.Nodes.Add(node);

If you try and reuse a node object after adding it to the tree view you will end up changing the items already assigned to the tree, as the TreeNode object is a reference type.

List Boxes and Tree Views in C#
List Boxes and Tree Views in C#
C#
TreeNode node = new TreeNode();
node.Name = "nodNewNode";
node.Text = "My New Node";

TreeNode node2 = new TreeNode();
node2.Name = "nodNewNode2";
node2.Text = "My New Sub Node (a)";
node.Nodes.Add(node2);

node2.Name = "nodNewNode3";
node2.Text = "My New Sub Node (b)";
node.Nodes.Add(node2);

Nodes can be removed from the list using the Remove method and passing in the node you wish to remove.

C#
treeView1.Nodes.Remove(node2);

If the above examples of node2 and node3 are not in scope you can Find a node by its name and remove it that way.

C#
TreeNode[] nodes = treeView1.Nodes.Find("nodNewNode3", true);
foreach (TreeNode oldnode in nodes)
{
  treeView1.Nodes.Remove(oldnode);
}

This method will also delete all sub-nodes of the selected node, so if you passed in "nodNewNode" it would delete that node and the two sub-nodes and you will be left with an empty tree.

You can also remove nodes by specifying an index and using the RemoveAt method as described above.

Iterating through Items

From time to time it may be necessary to iterate through a tree view object. The only way to loop through tree view nodes is to use a recursive algorithm.

C#
private void processNode(TreeNode node)
{
  MessageBox.Show(node.Text);

  foreach (TreeNode subnode in node.Nodes)
    processNode(subNode)
}

private void Test()
{
  foreach (TreeNode n in treeView1.Nodes)
  {
    processNode(n);
  }
}

Using Common Dialogue Boxes in C#

Visual Studio and Visual C# provide dialogue boxes for common tasks such as Open, Save and Print. In this tutorial, we will have a look at some of the dialogue boxes and see how we can load and save data in our program.

The common controls are listed under the Dialogues tab of the toolbox. You will have to drag these onto the grey area beneath the form editor, as they are non-visual components.

We are going to create menus and buttons for Open, Save and Save As. We will also need to add some simple logic to our program to detect modifications to the text. We will also look at the form closing events.

Add menu items for Open, Save and Save As to the menu strip we created in the last tutorial. You may wish to separate items with a horizontal line to group items of similar function. You can do this by just entering a - (minus symbol) to the text of an item, it will then change to a breaker bar. Don't forget to name each item appropriately.

There is a standard convention that should be observed regarding menu items which open a dialogue or another form, they should always end with an ellipses (three dots) to indicate another window will appear. For example "Save As...".

You should also set keyboard shortcuts to common tasks (such as Ctrl+C for Copy) and hotkeys for each time (Alt+Letter). Hotkeys are assigned by adding an ampersand before the letter, so "Save As" would become "Save &As". This will appear on the menu as "Save As".

My menu now looks like the image on the right, you can see how separators group the menu items, and the shortcut and hotkeys.

While we are adding menu items you can also create a Format menu after the File menu with submenus for Bold, Italic and Underline and assign the events we created in the last tutorial. If you wish, you can assign icons to the menu items in the same way as we add images to the toolbar buttons in the last tutorial.

Notepad Lite File Menu
Notepad Lite File Menu

Double-click on the open menu item to wire up the event and open the code editor. Key in the following code, which will display the dialogue box and load the contents of the file selected.

C#
private void evtOpenFile_Click(object sender, EventArgs e)
{
  if (openFileDialog1.ShowDialog() == DialogResult.OK)
  {
    richTextBox1.LoadFile(openFileDialog1.FileName,
      RichTextBoxStreamType.PlainText);
    saveFileDialog1.FileName = openFileDialog1.FileName;
  }
}

The ShowDialog method returns a DialogResult type based on which button was clicked by the user. In this case, we are only interested in acting if the user selected a file and pressed OK. The open file dialogue will store the selected filename within the FileName property, which can be passed into the richTextBox LoadFile method. We also need to specify the type of file using a RichTextBoxStreamType type of PlainText. The final line assigns the value of openFileDialog1.FileName to the equivalent property of the saveFileDialog for us to simply save the file without prompting for a filename.

When you run the program and open a file, you will notice that we now have a standard Windows open dialogue box that you should be familiar with. You may also notice that we can open any file, including text files, images or even executables. Ideally, we need to be able to limit the types of files that the user can open and we can do that by adding a filter to the OpenDialogBox properties.

Back in the form designer, click on the OpenDialog component and open the properties window and find the Filter property. We need to add a few file types that we want the user to be able to open. Surprisingly, Visual Studio does not give us a nice property editor for this, so we have to do it by hand. The format for the filter string is Description|Ext|Description|Ext and so on. For our program, we want to be able to open Text Files (*.txt) and Rich Text Files (*.rtf) so our filter string will be

C#
All Supported Files (*.txt; *.rtf)|*.txt;*.rtf|Text Files (*.txt)|*.txt|Rich Text Files (*.rtf)|*.rtf

Now when you run the program you will see that the user can only see files of type Text File or Rich Text File or Both.

Next, we will wire up the Save As menu item in a similar method. Double-click on the menu item to create the event handler method. We can copy and paste some of the code from the open method, changing a few of the variable names around. Don't forget to change the Filter property the same as our open dialogue, except we should remove the All Supported Files item.

C#
private void evtSaveAs_Click(object sender, EventArgs e)
{
  if (saveFileDialog1.ShowDialog() == DialogResult.OK)
  {
    richTextBox1.SaveFile(saveFileDialog1.FileName,
      RichTextBoxStreamType.PlainText);
  }
}

You can test this and it will save the current file to disk. The .Net platform will automatically check if a file exists and ask the user to confirm overwriting of the file. You can change this behaviour by altering the OverwritePrompt property of the Save dialogue.

Our final event is the Save method. This is an easy method but relies on our Save As method.

C#
private void evtSave_Click(object sender, EventArgs e)
{
  if (saveFileDialog1.FileName != "")
  {
    richTextBox1.SaveFile(saveFileDialog1.FileName, RichTextBoxStreamType.PlainText);
  }
  else
  { 
    evtSaveAs_Click(sender, e);
  }
}

First, we check if the FileName is empty. If we have a filename then just call the SaveFile method. If it is empty (i.e. a new document) we need to find out from the user what filename to save the data to so we just call the Save As action which has already been written to get a filename from the user.

There is one final method we need and that is to ask the user if they want to save changes on exit. C# provides an event on the form called FormClosing which is called when the form starts to close. From within this method, you can tell the form not to close, or perform some actions that must be executed at the end of the program (i.e. closing connections or files).

We can use this function to see if the RichTextBox needs to be saved and prompt the user.

C#
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
  if (richTextBox1.Modified) 
  {
    DialogResult result = MessageBox.Show("Do you wish to Save changes?", "Save Changes", MessageBoxButtons.YesNoCancel);

    if (result == DialogResult.Yes)
      evtSave_Click(sender, e);
    else 
      if (result == DialogResult.Cancel) 
        e.Cancel = true;
  }
}

And there we have it, our Notepad Lite application is coming along nicely, and we have learned how to use save and open common dialogue boxes as well as save and load text files.

Menus, Popups and Toolbars in .Net Forms and C#

The two most common types of menus are the standard drop-down menu and the pop-up context menu. These are both found within the Menus & Toolbars tab of the toolbox.

This tutorial is specific to .Net 2.0 and above. In previous versions, a completely different set of components were used which did not have any support for OS visualisations (skins) and they were based on old Win32 technology. The .Net 2.0 versions of these controls are skinnable, draggable, storable and in line with the modern XP/Vista user interface theme.

The Menu Strip and Context Menu Strip

Both controls can be dragged onto a form, and since they are 'non-visual' components they will appear in a grey area below the form designer. By clicking on the menuStrip or contextMenuStrip the form designer will show a menu that you can click and type values into, both controls behave in the same manner. The designer will automatically expand to show sub menus.

Visual Studio Menu Designer
Visual Studio Menu Designer

Add a menuStrip component to your form, and create a File menu with two sub-items called New and Exit, making the n and x hotkeys.

When you give a menu item a title, you can use the & symbol to define a hotkey, for example, &File will allow the Alt followed by the F key to open the file menu. We will also provide a shortcut key to the new document item by selecting it and changing the ShortcutKeys property of the item. Shortcut keys are usually actioned with the control key, for example (Ctrl+N) for a new document. Finally, we should give the menu item a meaningful name such as evtNewDocument and evtExitProgram. We suggest using the evt prefix as we are dealing with an event (not a C# event, but a user event such as opening a file, saving a file, making a selection bold etc...), but you could also use mnuNewDocument if you wish.

Toolbars

Toolbars are another method for program navigation. They are commonly a series of buttons along the top of the application, just below the menu. They should be the most common features, or most often used.

Let's create a toolbar on our form by dragging a ToolStrip onto the form. This will allow us to create some buttons and link them to actions. You can create a button on the tool strip by clicking on the down arrow that appears and from there you can select any of the controls on the list. Alternatively, you can right-click on the tool strip and select Insert from the menu, and add a button from the submenu. This is going to become our New Document button.

You should now give your new button a name, such as btnNewDocument, and give it a meaningful Title and ToolTipText. The title is the text that appears when icons are not shown, and the ToolTipText should be changed to reflect the function that the button performs. The ToolTipText will appear when your mouse is hovered above the button and is usually shown in a yellow pop-up box.

It would be a good idea to give the button a meaningful icon. Visual Studio 2005 gives you a large icon library to choose from, which is located in C:\Program Files\Microsoft\Visual Studio 8\Common7\VS2005\Image\Library. There is a ZIP archive that you can extract to obtain all the icons; alternatively, you can use any image from the web or hard drive. I used the new document image located in the bitmaps/commands/32bitcolor folder. You may have to change the transparent colour if the image does not look correct. This is a property in the properties and events window. When adding icons to your program, select Project Resource File rather than Local Resource, so that the icon can be reused throughout the project.

Adding a Rich Text Editor

To make our sample program a little more functional, we are going to add a rich text editor to the form. A rich text editor will provide an area we can type text into, and at a later date, format it.

Drag a RichTextBox control onto the form and you will see that the control is small, and does not resize when you maximise the window. What we need to do is tell the control to fill out the form, a process known as docking. Back in the editor, select the RichTextBox and click on the little arrow in the top right, then select "Dock in parent container". Now try maximising the form or resizing it and notice how the RichTextBox always fills the entire form.

Expand the common format settings window.
Expand the common format settings window.

Adding Some Events

To be useful, a menu or toolbar must have an event associated with it. This is done in the same way as adding an event to a button or form: by double-clicking it, or by double-clicking the Click event in the properties window. This will open up the code editor with a new method already declared. All you have to do is type in the code for the action it should perform.

Double-click on the exit menu item to launch the code editor and type in the following code to close the program.

C#
private void evtExitProgram_Click(object sender, EventArgs e)
{
  Close();
}

Next, double-click on the New menu item and add the following code:

C#
private void evtNewDocument_Click(object sender, EventArgs e)
{
  richTextBox1.Clear();
}

Delegate Events in Action

When we created the New Document menu item, we also created a method called evtNewDocument_Click to handle the click event. We can use that same method on our toolbar button Click event. Click on the toolbar button for New Document that we created and on the properties windows, press the lightning symbol to change to events and find the Click event. On the right-hand side, you will see a drop-down arrow, which expands a list of events that match a click event signature. You should see our evtNewDocument_Click listed and you can select it.

We now have a menu item and a button calling the same method. This not only saves coding time but reduces maintenance overheads and code duplication.

Testing

Run the program and type some text into the RichTextBox, try out the toolbar button and it will clear the contents of the text box. Type some more text into the box and try the new documents menu item. It will also clear the contents of the text box. Now exit the program using File » Exit.

Popup Context Menus

A context menu is typically the "right-click" menu in Windows. These behave in the same way as a regular menu strip, except that they are not visible at design time. To add a context menu simply add a context menu strip from the toolbox to the form and it will be added in the grey area at the bottom of the form designer. Click on it to edit the context menu, and add items for Bold, Italic and Underline. Also, give the items correct names, and optionally apply a font style to the menu items using the Font property in the properties window.

Next, we need to assign the Context Menu Strip to the RichTextBox, so click on the RichTextBox and in the properties window, locate the property called ContextMenuStrip and drop it down and select the new context menu strip. You can test this by running the program and right-clicking on the rich text box. The popup menu will appear each time next to the mouse pointer.

Back in the editor, we will now add some events to the context menu. Double-click on each of the items in turn and add the code below as appropriate.

C#
private void btnFormatBold_Click(object sender, EventArgs e)
{
  richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, 
    richTextBox1.SelectionFont.Style ^ FontStyle.Bold);
}

private void btnFormatItalic_Click(object sender, EventArgs e)
{
  richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, 
    richTextBox1.SelectionFont.Style ^ FontStyle.Italic);
}

private void btnFormatUnderline_Click(object sender, EventArgs e)
{
  richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, 
    richTextBox1.SelectionFont.Style ^ FontStyle.Underline);
}

Now you can run the program and test the popup context menu, changing the font styles with the popup menus.

Notepad Lite Application
Notepad Lite Application

And there is your first Windows application - Notepad Lite!

Using Multiple Forms in C#

There are two different types of multiform applications, those where another form is used as a dialogue box, i.e. settings or about, and another where there are multiple forms that can all be accessed at the same time, or switched between, such as Microsoft Word. This is known as Multiple Document Interface. This tutorial deals with the former scenario; we will add a new form to our Notepad Lite application and have it manipulate the contents of the text box. We will look at project scope, namespaces and global variables.

To create a new form in Visual Studio or Visual C# Express, click on the Add New Item icon and select Add Windows Form, or you can right-click your project on the Solution Explorer, or select File > New > File... and select Windows Form. This will create a new blank form that will form the basis of an Insert Text box. Go ahead and give the new form a name (frmInsertDateTime) and title (Insert Date/Time). Since we do not want this form to be sizeable or maximised/minimised we can disable these features by setting the FormBorderStyle to FixedDialog and MaximizeBox and MinimizeBox to false.

Create a new form in Visual Studio
Create a new form in Visual Studio

We will also add a listBox (lstFormats) and two buttons (btnInsert and btnClose). Set the form's AcceptButton property to btnInsert and the CancelButton property to btnClose. This will handle the return key and escape key actions.

Next, I created a list of date format strings to show in the list box. I declare the list at the top of the class and add items in the form's constructor, and then when the form is loaded I can iterate through the list and add the items to the list box.

C#
public partial class frmInsertDataTime : Form
{
  List<string> dateFormats = new List<string>();

  public frmInsertDataTime()
  {
    InitializeComponent();

    dateFormats.Add("{0:d}"); / 08/12/2007
    dateFormats.Add("{0:D}"); / 08 December 2007
    dateFormats.Add("{0:t}"); / 15:27
    dateFormats.Add("{0:T}"); / 15:27:40
    dateFormats.Add("{0:f}"); / 08 December 2007 15:27
    dateFormats.Add("{0:F}"); / 08 December 2007 15:27:40
    dateFormats.Add("{0:g}"); / 08/12/2007 15:27
    dateFormats.Add("{0:G}"); / 08/12/2007 15:27:40
    dateFormats.Add("{0:M}"); / 08 December
    dateFormats.Add("{0:r}"); / Sat, 08 Dec 2007 15:27:40 GMT
    dateFormats.Add("{0:s}"); / 2007-12-08T15:27:40
    dateFormats.Add("{0:u}"); / 2007-12-08 15:27:40
    dateFormats.Add("{0:U}"); / 08 December 2007 15:27:40
    dateFormats.Add("{0:Y}"); / December 2007
  }

  private void frmInsertDataTime_Load(object sender, EventArgs e)
  {
    lstFormats.Items.Clear();
    foreach (string format in dateFormats)
    {
      lstFormats.Items.Add(String.Format(format, DateTime.Now));
    }
  }

Note that date formatting is dependent on the system's regional settings; the example strings here are from my local locale (en-gb).

Back on our main form (frmMain) we need a way to open this new form. To do this, we must first create an instance of frmInsertDateTime, and then call its Show method. Add this code to the dateTimeToolStripMenuItem_Click() method.

C#
frmInsertDateTime frmInsertDateTime = new frmInsertDateTime();
frmInsertDateTime.Show();

Next, we need to add a main menu "Insert" with an item titled "Date/Time...". Be sure to name the items correctly and in line with the rest of the menu items created.

The next thing we need to do is assign actions to close the form and insert the text into the text editor.

On the frmInsertDateTime dialogue designer, create methods for btnClose by double-clicking it and adding the following code.

C#
this.Close();

The code for inserting the text is a little more complex, so we will have a look at that in a minute. When you run the program to test it you will be able to click on the menu item and the form will show with the list box filled with the current date and time in different formats. You can select a date time format and close the date time form.

To access the richTextBox control on the main form from within our other form, we need to change a few lines of code. Firstly, we need a way to reference the object frmMain rather than the class frmMain, the easiest way is to send the object as a parameter to the constructor and reference that.

In the frmInsertDateTime source, we modify the constructor to read as below:

C#
private frmMain theParent;

public frmInsertDateTime(frmMain Parent)
{
  InitializeComponent();  
  dateFormats.Add("{0:d}"); / 08/12/2007
...
  dateFormats.Add("{0:Y}"); / December 2007
  
  this.theParent = Parent;
}

Notice the parameter, variable declaration and assignment. Next, we need to create a public property that we can use to access the private control for frmMain.

We need to modify the frmInsertDateTime.Show() line to pass the frmMain object:

C#
frmInsertDateTime.Show(this)

After the frmMain constructor add this property:

C#
public RichTextBox RichEditor 
{ 
  get { return richTextBox1; } 
  set { richTextBox1 = value; } 
}

This will allow us to read and write to the control from another form. Back to the frmInsertDateTime code and we can now add a line to insert the text:

C#
theParent.RichEditor.SelectedText = lstFormats.Items[lstFormats.SelectedIndex].ToString();

Now when you run the program we have a fully functioning custom dialogue box that can access a control on another form

Using Multiple Forms in C# Applications with MDI

Multiple Document Interface (MDI) allows one form to have multiple forms contained within it, like multiple Word documents. It allows a group of windows to be contained and managed within a parent form. The child forms all inherit from a single form class and all contain the same controls.

Visual Studio does all the hard work for you, all you have to do is create a new Windows Forms application and then from the Add a new item dialogue select MDI Parent, give it a name and click OK. Visual Studio will create all the forms, buttons, toolbars and menus that a basic application will need. Right-click on Form1 and click on "Exclude From Project". Next, open program.cs and change the line:

C#
Application.Run(new Form1());

to

C#
Application.Run(new MDIParent1());

This will change the start-up form of the project to the new MDI form.

You can run the application now and test the features. You can create as many new forms as you like; some dialogue boxes are linked up while others have placeholders. One thing you should notice is the Windows menu. This lists common items such as Cascade and Tile Vertical as well as listing the child forms already opened. Menu items to control the layout (Tile, Cascade, Minimise, Arrange Icons etc...) all interface with the forms LayoutMdi method, passing in an Enum.

C#
LayoutMdi(MdiLayout.TileHorizontal);

You can iterate through all the open documents:

C#
foreach (Form childForm in MdiChildren)
{
  childForm.Close();
}

A lot of the functionality has been included in the example project supplied, I'll leave it for you to create your own MDI application.

Multiple Document Interface (MDI)
Multiple Document Interface (MDI)

Creating Controls for Windows Forms and C#

Just like ASP.Net, Windows forms allow the creation of custom controls to extend or enhance existing controls or to create brand-new functionality.

Like ASP.Net, there are different types of a custom control in WinForms, some with a designer to add controls (User Control or Composite Control) and others that exist purely in C# (Custom Control) and allow greater freedom in drawing and graphics. You can also create a normal C# class and create inherited controls.

There are many reasons why you may want to extend an existing control. Maybe you need to change the default properties, override the Paint method, and add validation events by default. In this tutorial, I will show you how to extend some of the basic controls and extend their functionality.

Extending a Button control

The simplest control to look at is the button control. I'm going to create a new control inherited from a button and I'm going to change a few of the default properties. The reason for doing this is so that all buttons in the application can have the same class and set of properties. If a change needs to be made, a quick modification to the class changes all the buttons in the project. By contrast, if you added the base button control and changed all the properties manually, you would have to go through all the forms in the application and update each button manually.

I used this technique while developing a touchscreen interface. I needed each button to be larger and have a different colour scheme but didn't want to apply the properties to all of the buttons individually. All you need to do is add this control to the form instead of the base button.

To create an inherited control, simply create a new C# class file with a meaningful name and set the class to inherit from the base class, as shown below.

C#
using System;
using System.Windows.Forms;
using System.Drawing;

// <summary>
// Summary description for TouchscreenButton
// </summary>
public class TouchscreenButton : Button
{
    public TouchscreenButton()
    {
        this.Width = 100;
        this.Height = 75;
        this.FlatStyle = FlatStyle.Flat;
        this.Cursor = Cursors.Hand;
        this.ForeColor = Color.Black;
        this.BackColor = Color.White;
        this.FlatAppearance.BorderSize = 2;
        this.FlatAppearance.BorderColor = Color.Navy;
    }
}

When you add this class and build the project, you will see a new section in the toolbox with the name of your project, and within that an entry for a TouchscreenButton. We'll have a look at the toolbox and options later in this tutorial.

Each time you add a TouchscreenButton to the form, it will have the same default properties as specified above. This is incredibly handy if you are using multiple controls on multiple forms.

Creating Custom Controls for Windows Forms
Creating Custom Controls for Windows Forms

You can also instantiate controls and add them to a form with code and you need not set all the properties.

C#
TouchscreenButton tbtnMyButton = new TouchscreenButton();
placeHolder1.Controls.Add(tbtnMyButton);

You can use this method to override or extend methods, add additional properties or change the behaviour of an existing control.

User Controls

User controls allow you to use the designer to create a composite control (a control made up of other controls). For example, you can add a textbox and a button to the same control and add this new control to a form to save time and effort. This new control handles the logic rather than the form so it aids in scalability and reusability.

To create a new user control, add a new item to the project and select User Control.

I'm going to create a control that will handle file browsing, and simulate a process. This will have a textbox for the filename, a button to select a file, a button to process the file and a progress bar for a simulated process. Using the designer and creating the code behind is just like designing a form so I won't go through this process. You can download the code at the end of this article.

Creating Controls for Windows Forms
Creating Controls for Windows Forms

When using this control in an application, all you need to do is to add the control from the toolbox. All the boxes, buttons and logic will be handled already and your application does not need to do anything. If you choose to add some events to the user control (validate filename, or delegate the process method) your client application can simply subscribe to the events as it would any other control.

Creating Controls for Windows Forms
Creating Controls for Windows Forms

Custom Controls

The final control type is the custom control. This does not have a designer but does let you draw your own graphics. In this part of the tutorial, I am going to create a Smiley control that displays a smiley face.

You can create a custom control by adding a new file to your project and selecting Custom Control.

The OnPaint() method is used to draw shapes using the PaintEventArgs.Graphics property. In a more realistic environment, you would use this to draw graphs or charts, but for this example, I'll draw a smiley.

The code behind looks like this:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Smiley : Control
    {
        public Smiley()
        {
            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            / Draw a basic smiley face
            pe.Graphics.FillEllipse(Brushes.Yellow, 0,0,this.Width-1, this.Height-1); / Face
            pe.Graphics.FillEllipse(Brushes.Black, (this.Width / 4), (this.Height / 4), (this.Width / 6), (this.Height / 6)); / Left Eye
            pe.Graphics.FillEllipse(Brushes.Black, this.Width - (this.Width / 3)-10, (this.Height / 4), (this.Width / 6), (this.Height / 6)); / Right Eye
            pe.Graphics.DrawArc(Pens.Black, (this.Width / 4), (this.Height / 2), (this.Width / 2), (this.Height / 4), 0, 180); / Mouth
            
            / Calling the base class OnPaint
            base.OnPaint(pe);
        }
    }
}

It's only basic, but it shows how to draw using the graphics and what's more it will scale when the control is resized. This is what it looks like on the form:

Creating Controls for Windows Forms
Creating Controls for Windows Forms

That's just about it for the controls. We've seen how to create inherited controls, user controls and custom controls.

Adding Properties

You can add a property to the property window for your control simply by creating a public property.

C#
private string _smileyName;
public string SmileyName
{
    get { return _smileyName; }
    set { _smileyName = value; }
}

You can use this method for any of the basic data types such as int, string, bool, decimal and so on. You can also use this to create an advanced data type such as an enum as shown in the example below.

Control Properties
Control Properties
C#
public enum SampleColours
{
    Red,
    Green,
    Blue,
    Yellow
}

private SampleColours _smileyColor;
public SampleColours SmileyColor
{
    get { return _smileyColor; }
    set { _smileyColor = value; }
}

This will be shown as a drop-down list containing the items in the enum.

Control Properties
Control Properties
Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 20 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. DV

    On Wednesday 21st of September 2016, Divyesh Vaghela said

    I am a begginer in C# windows forms application development. I have learned about most of the important controls and components and I learn the actual implementation of the common dialogue controls from this page. So thank you very much...

  2. MC

    On Friday 17th of June 2016, Maimoona ch said

    can u help how can we add smily face in richtextbox by click on smiely button app(like yahoo email app ) in c#

  3. PE

    On Wednesday 12th of December 2012, Pete said

    Very much appreciate all your tutorials. Very concise with exactly the right amount of detail. Thank you very much!

  4. CE

    On Tuesday 4th of September 2012, CE said

    Great tutorial -- I looked for hours before a found an excellent example without navigating through the whole site.
    I bookmarked your site -- I'll definitely be back !!

  5. VA

    On Wednesday 7th of March 2012, Vaidee said

    I have exactly same problem as James has - does not contain a constructor that takes '0' arguments.

    Also the list of date formats does not get populated at all ?
    what could be going wrong. I reviewed the code over and over again, but could not fathom why this is not getting populated.

    I must however say this is a great tutorial and I have benefitted most.

    Do kindly respond as I would like to see this project properly completed.
    Thanks a lot.

  6. EV

    On Wednesday 11th of January 2012, eb-5 visa said

    Good and useful tutorial for beginners.It helps me a lot.

  7. LL

    On Friday 16th of December 2011, LLB said

    I have a similar UserControl application. it works quite good when I debug it but if I put it in a form application and change a property, I take "Object reference not set to an instance of an object" error although I defined the property 'public'?

  8. MA

    On Saturday 3rd of September 2011, Matt said

    Short, concise, beautiful.

  9. JT

    On Thursday 16th of June 2011, jt said

    Excellent Article!

    I do have a question...

    I was playing with adding another smiley (green) dynamically, that would draw to the right of the existing yellow smiley. It doesn't seem to do what I had expected.

    Here's the Form1.cs code:

    C#
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
           Smiley smiley;
    
            public Form1()
            {
                InitializeComponent();
    
                smiley = new Smiley(10,10);
    
                smiley.Location = new System.Drawing.Point(145, 145);
                smiley.Name = "smiley2";
                smiley.Size = new System.Drawing.Size(120, 120);
                smiley.SmileyColor = WindowsApplication1.Smiley.SampleColours.Green;
                smiley.SmileyName = null;
                smiley.TabIndex = 5;
                smiley.Text = "smiley2";
    
                smiley.Visible = true;
    
            }
        }
    }

    Thanks,

    jt

  10. HS

    On Thursday 14th of April 2011, Helmut Scheiss said

    Best friggin' example I've ever seen. Just in case some people had trouble completing the service reference in VS 2010 :
    The Add Server Reference dialog box will then communicate with the web service and download the WSDL and display the service and any methods it exposes. The serice we created is listed under Services->SoapService.

    Click the "Advanced Button", then click on the "Add Web Reference" button and continue from there.

  11. PE

    On Thursday 16th of December 2010, Peter said

    Thanks a lot, you're a star!
    Used quite some time to figure this out and your tutorial just made it so easy that I'm almost crying :-)

  12. MA

    On Sunday 10th of October 2010, matsolof said

    Good and useful tutorial for beginners.

  13. MA

    On Monday 4th of October 2010, matsolof said

    Interesting tutorial for a C# beginner like me.

    I understood most of it up to this line:

    "Add this code into the dateTimeToolStripMenuItem_Click() method."

    What does this mean? Where do I put the code?

    I would appreciate an explanation, as would other C# beginners, I think.

  14. JC

    On Tuesday 27th of July 2010, Jeff C said

    The zip file does not contain all the necessary files. It is missing the form named frmInsertDataTime.

  15. RI

    On Tuesday 6th of July 2010, riper said

    Excellent article! Thanks for describing something rather complex in so few words! :)

  16. BA

    On Saturday 20th of February 2010, Balachandran said

    It's work perfectly. Thanks..
    Thanks..Thanks..Thanks..Thanks..Thanks..Thanks..

  17. CM

    On Thursday 8th of October 2009, Cormac Miller said

    >The only way to loop through treeview nodes is to use a recursive algorithm.
    No it's not. If you can recurse, you can iterate, albeit not as elegantly...

  18. JA

    On Thursday 13th of August 2009, James said

    Hi,
    Thanks for these tutorials, very useful newly coming from VB/VBA. I following the above, am having trouble with the line frmInsertDateTime frmInsertDateTime = new frmInsertDateTime(); which gives the error 'WindowsApplication1.frmInsertDateTime' does not contain a constructor that takes '0' arguments.
    I cannot see where I have gone wrong - would you be so kind as to send me a zip file of the whole thing?
    Kind regards
    James

  19. AN

    On Thursday 13th of August 2009, Anish said

    Very useful article..Keep it up n thanks a lot..

  20. JA

    On Friday 3rd of October 2008, Jason said

    You have done an awesome job with all of your tutorials dude, keep up the great work!!!!! I'd olve to see heaps more, I have learned so much from you.

    Thank you,
    Jason.