How to create a WinForms MDI application? - part 3

July 23rd, 2008 by ganton | Print

This is the third post in the series. The second one post describes Business Logic Layer (BLL) of the application. BLL contains two types of classes entities and managers. Here, an entity class contains the information of a business object retrieved from database but it is not equal or the same to those object generated in DataContext in Data Access Layer (DAL). A manager is a class which implements different operations like retrieving specific information, creating new entity object, updating, deleting and other business operations. There are two entities and one dummy interface for them named Car, CarMaintenance and IObect. Accordingly, there are two manager classes and one interface for them named CarManager, CarMaintenanceManager and IObjctManager.

(All posts in this series: Post 1, Post 2, Post 3, Post 4, Source Code)

In this post I’ll present a part of the presentation layer. In this sample the presentation layer is the end application. The application is build using MDI model. The application should be able to validate information written in input fields by end-user and also to manage MDI parent’s child forms. To support data validation I’ve created a simple set of classes used for data validation. It also should support opening different forms without to reopen them if they are already opened but there are also exceptions when more then one instance of the form should be opened. The application also should provide an easy access to opened forms.  To support this requirement I’ve created a forms manager.

For data validation I have an interface IValidator. All validation classes implements it. It has two properties Control and ErrorMessage. The first one is the control to validate and the second is the message to display if entered value is not valid. It also contains a method named Validate returning true if entered value is OK, otherwise false.It is declared as internal because I’m using it only in this executable.

[sourcecode language="csharp"]

internal interface IValidator
{
Control Control { get; set; }
string ErrorMessage { get; set; }

bool Validate();
}

[/sourcecode]

For validating integer values I’ve created a class named IntValidator. Its Validate method validate the value and if it is what is expected returns true, otherwise false.

[sourcecode language="csharp"]

internal class IntValidator : IValidator
{
#region IValidator Members

public Control Control { get; set; }
public string ErrorMessage { get; set; }

public bool Validate()
{
int value;
return int.TryParse(Control.Text, out value);
}

#endregion
}

[/sourcecode]

There are similar classes for validating decimal and for validating a required value. It is clear that these classes will be as much as needed for validating all type of data we expected to be entered. Diagram below depicts all classes in data validation group.

In addition, there is a ValidationManager class. It contains a list of assigned to it validation classes and an error provider to use for displaying an error of a control. It also has a Validate method where it goes through all validation classes in the list and calls their Validate method. If a result of validation class Validate method is false it displays an error message using ErrorProvider class object to its Provider property. Click to see its implementation.

As I mentioned above we need a class to manage MDI parent’s child forms in a specific way. For this purpose a static class named FormsManager is created.

It has three private fields for holding MDI parent form of the application, a ToolStrip control used to display and provide easy access to all opened forms and a dictionary of all opened forms. It has four public methods. The first one is Configure. It accepts a Form which should me a MDI container and a ToolStrip control used to display opened forms. If both parameters are OK it configures object itself. Next there is a method used to open forms only once named OpenForm. It accepts a Type of the form to be instantiated and opened and a params parameter which is an array of objects. The use of the second method is a bit specific. They should be set as pairs <property_name>, <property_value>. This method returns true if requested type of form was opened, otherwise false. There is a similar method named OpenMultipleForm. It allows to instantiate many objects of a specified type. It requires one more parameter named key. Based on the key and type name a new key is created and it is used to check and store a new object into a dictionary. The key is also used when ToolStrip button is created to set its Text property. The last pubic method is CloseAllForms. It is clear that calling it we will close all opened forms in the MDI container. Private methods and event handlers are intuitive and I think that if you go through the code you’ll understand what they do. Feel free to ask any question or to make any suggestion in comments. Click to see FormsManager class implementation.

The last class I’d like to present here is a very simple class but it is a very useful class. It is ExecuteActionHelper class. I do not remember how the idea of it came but it was in my old company. I think in one discussion or meeting an idea of such helper arised. But it is not important! the important moment here is that this class has a method named ExecuteAction. It accepts a delegate of type ExecuteActionDelegate and invokes it. The nice here that we can have a centralized control of all exception and whatever like to make some performance checks etc. This class should be used in each event of a form. In this simple application It does nothing just display a message if an error occurs.

[sourcecode language="csharp"]

public delegate void ExecuteActionDelegate();

public static class ExecuteActionHelper
{
public static void ExecuteAction(ExecuteActionDelegate action)
{
try
{
if (action == null)
{
return;
}
action.Invoke();
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), “Application Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
}

[/sourcecode]

I think it is for today. In the next post I’ll finish the presentation of this MDI application and you’ll be able to see how classes presented today are used and how the application looks like. The full source code of the application will be provided,

Leave a Reply