Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Centralize Show Form Validation Logic

0.00/5 (No votes)
17 May 2005 1  
This article will show how to centralize your logic when opening a Windows Form.

Introduction

This article is intended to show you an easy way to centralize your logic when opening a Windows Form.

Background

It is common that when developing a Windows application you will want to perform either some type of operation or validation that will determine whether a form can be opened. Many times the same code will need to be executed in different places throughout your project. Obviously a good design will not litter the application with the same code over and over again. So, why not use the constructor of a form to perform any operation or validation logic prior to opening the form? Using the constructor of a form to do certain operations does have limitations. For instance, if you have FormA and you perform all security validation(s) in the constructor, nothing will stop the developer from doing the following and making the form visible to the user:

FormA frm = new FormA();
FormA.Show();

In this example, putting security logic in the FormA constructor is too early and we want to defer that logic to a later point in time. Putting the logic in the Show() method would be the latest point prior to the form opening. Doing this also forces your code to be more defensive.

Another question someone may ask is why not put the security logic in the Activated, Enter or Load events of the form? In some situations that would be fine, but the raising of these events actually infers the form may have been made visible to the user. Your code will not be very clean if you are to put the same logic into every event handler previously mentioned. If the form cannot be made visible to the user, for whatever reason, it is simpler to stop the process before the events are raised.

Assumptions

I am making a couple assumptions when proposing this solution:

  1. The code base you are working with has a base form where all of the forms in your project inherit from.
  2. The constructor is being used for initializing the presentation of the form.
  3. The constructor is not being used to perform any logic that will be used to determine whether the form will be opened.
  4. The constructor is not performing any logic that will be committed to any objects that are passed into the form's constructor. This is important because if the constructor is committing a new state to an object passed into the form's constructor, and the form will not be opened when the Show() or ShowDialog() methods are called, you will be in a not so happy place.

Solution

To solve this problem, we will simply use the keyword new to override the base implementation of Show() and ShowDialog() in the base form (BaseForm) of our project. A derived Windows Form cannot override the Show() and ShowDialog() methods, so we will override the methods using the keyword new, insert our own logic and then call to the base method.

public new virtual DialogResult ShowDialog() {
     if (CanOpenForm)
          return base.ShowDialog();

     ShowFormError();
     return DialogResult.None;
}

public new virtual DialogResult ShowDialog(IWin32Window owner) {
     if (CanOpenForm)
          return base.ShowDialog(owner);

     ShowFormError();
     return DialogResult.None;
}

public new virtual void Show() {
     if (CanOpenForm) {
          base.ShowDialog();
     } else {
          ShowFormError();
          return;
     }
}

protected virtual bool CanOpenForm {
     get {
          ///preform general validation logic for opening all forms here.

          return true;
     }
}

protected virtual void ShowFormError() {
     ShowFormError("Form could not be opened.");
}

protected virtual void ShowFormError(string sErrorMessage) {
     ShowFormError(sErrorMessage, "Form Open Error", 
                 MessageBoxButtons.OK, MessageBoxIcon.Error);
}

protected virtual void ShowFormError(string sErrorMessage, string sCaption, 
     MessageBoxButtons buttons, MessageBoxIcon icon) {

     MessageBox.Show(sErrorMessage, sCaption, buttons, icon);
}

Let's now review the above code. The Show() and ShowDialog() methods all check the CanOpenForm property before the base method is called. You have the option of making a different CanOpenForm property for each Show() or ShowDialog() method but more than likely using the same property will be good enough. Note that the CanOpenForm property has been made virtual, this is so all derived forms can override this property and add form specific validation. Also note that I have made Show() and ShowDialog() virtual so you can completely override the validation logic on a derived form.

Note that in the overrides of ShowDialog(), specifically return DialogResult.None if CanOpenForm failed. This is because base.ShowDialog() by default will return DialogResult.None. If the user were to press the "X" in the top right hand corner of a modal dialog form, DialogResult.Cancel would be returned. We do not want to return that value because it would infer that the dialog form might have been made visible to the user when in actuality it had not.

Another neat thing you can do is to ensure that a form is being opened properly. For instance, let's say your project has a BaseForm and BaseDialogForm that inherits from the BaseFrom. The BaseDialogForm is meant to be a modal form that all other modal forms (with OK and Cancel buttons) will inherit from. Since this from is a modal form, you may want to override the Show() method.

public override void Show() {
     System.Diagnostics.Debug.Assert(false, 
               "All Dialog Box Forms should be modal.");
     base.Show();
}

When overriding the base Show() method, I simply send a debug assert to the developer saying that this method should not be used. Although the method still calls the base.Show(), it is not overly obtrusive in its implementation. You have many other options:

  1. Force the issue by calling System.Diagnostics.Debug.Fail or do not call any method at all.
  2. Force the overridden Show() method to call ShowDialog().
  3. Anything else, there is no hard and fast rule, it is what ever makes sense.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here