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

Edit State aware Form with customizable controls

Rate me:
Please Sign up or sign in to vote.
4.11/5 (5 votes)
1 Feb 20055 min read 54.1K   422   35   10
Reuseable form class, including typical modal buttons that detect any edit changes on any control on the form and sets form state to dirty, enabling OK and Apply buttons.

Sample Image

Introduction

Many times, when doing typical Windows apps, one comes across the need to monitor all controls on a form to see if any edits have occurred.

While working on a C# Windows application recently, I had gone through the process of manually hooking up many 'changed' events, setting a dirty flag, and enabling OK, Apply buttons on two forms. Realizing that I would need to do this scenario repeatedly for many more forms, I decided that a base form class that implemented this functionality was called for, and this, I created: FormEditState.

Man, that animated GIF is annoying. I won't do that again ;-)

Using the code

FormEditState is implemented as a class library DLL, called, appropriately enough FormEditState.dll. It offers two reusable classes:

  • ESForm - Form derived class to implement recursive control detection, hosts EditStateFormButtons and allows flexible functionality.
  • EditStateFormButtons - class to implement typical GUI for submission buttons (OK, Cancel, Apply and Help).

Just reference this DLL in your project and derive any Form you may be using from ESForm. Note the namespace FormEditState.

C#
namespace MyProject {
    public class MyForm : FormEditState.ESForm {...

For the most part, ESForm will do what it needs to do without any additional coding. The default actions are to scan all controls (and recursively scan all sub-controls) on the form and monitor them for any edits. Currently, I hook into events for all Edit controls, ListBoxes, ComboBoxes, RadioButtons, CheckedListBoxes, UpDown controls, Trackbars, and TreeViews. Look at ES_AddControl(...) in ESForm.cs for code to hook into these controls, and add additional controls there if desired. It will recurse into all control containers, including tabbed controls. Based on the control type, the most appropriate event is hooked for that purpose.

All that is required for a useful implementation is to override one or more of the following virtual functions:

C#
protected virtual bool OnOK()
protected virtual bool OnApply()
protected virtual bool OnCancel()
protected virtual void OnHelp()

It should be fairly obvious what these will do. They will get called whenever the corresponding button gets clicked. For the functions that return bool, returning true will allow that action to take place, so in the case of OnOK(), returning true will allow the form to close. Any validation code should be implemented in these functions, and if the form data is invalid, return false. Returning false from OnOK() or OnApply() will also keep the current form state as dirty. Returning false from OnCancel() will abort form cancellation. The default implementation of these functions all return true , except OnHelp() which does nothing.

For a working example of how to hook up ESForm, look at Form2.cs in the subproject TestHarness.

ESForm also implements the following functions and events, listed in approximate order of usefulness:

C#
void ES_EnumerateEditableControls()
void ES_EnumerateEditableControlsExcept(params Control[] NoDetectControls)
void ES_AddControl(Control C, bool bRecurseChildren)

It is not specifically necessary to call ES_EnumerateEditableControls() as it will be called automatically the first time the form is activated, if no controls have been scanned. If you wish, you may call it implicitly in Form.Load.

ES_EnumerateEditableControlsExcept(...) allows you to recursively scan all form controls except any that are given as parameters. If for some reason you don't want to monitor one or more controls, use this method.

ES_AddControl(...) allows for the selective addition of one control, and may be called multiple times. Its bRecurseChildren parameter controls whether or not it will descend into child controls.

C#
void ES_SetFormEdited()
void ES_SetFormClean()
void ES_DetectEditedState(bool Detect)
bool ES_IsEdited()

The above functions are used to control and detect the Dirty or Edited state of the dialog:

ES_SetFormEdited() will immediately flag the Form as Dirty, and enable OK, Apply. You could add this function to any controls I did not directly support, such as grid control event handlers. To see what controls I did support, look at ES_AddControl(...) in ESForm.cs. Most of the common controls are wired in.

ES_SetFormClean() does just that. Form is flagged as clean, and OK, Apply will be disabled.

ES_DetectEditedState(...) is a very useful function as it can suspend detection of edit changes. The use for this is, if you change a control's value at runtime and don't want to unintentionally trip the Dirty flag. Calls to this function should be balanced, and disable detection, make any runtime changes, and re-enable detection.

ES_IsEdited() will return true if the form has been edited (go figure).

C#
virtual bool ES_Control_Edited(object sender, EventArgs e)

This function can be overridden to intercept edit detection. Returning false will stop flagging the form as edited. It is used in Form2.cs to show a textual report of what control was edited. sender is the control that generated the event. To use this function, you will need to determine what run time class type sender is, to act appropriately.

There are a few other useful events and functions in ESForm, but for the most part, the above will accomplish all desired functionality.


EditStateFormButtons class was designed for use by ESForm, but it can be used as a separate component, if desired. It has a number of properties and methods to adjust its control ordering and positions, to suit your needs. Visually, it may be presented either horizontally or vertically, determining this arrangement by whether it is docked top/bottom or right/left:

Image 2

A very important property of EditStateFormButtons is ButtonsDisplayed. This has an enumeration that controls button ordering and whether or not the Apply and/or Help buttons are shown. I have provided what I consider to be every useful variant of these button configurations you may need:

  • OKCancelApply
  • OKCancelApplyHelp
  • CancelOKApply
  • CancelOKApplyHelp
  • OKApplyCancel
  • OKApplyCancelHelp
  • ApplyOKCancel
  • ApplyOKCancelHelp
  • OKCancel
  • OKCancelHelp
  • CancelOK
  • CancelOKHelp

Another useful property is ShowSeparatorLine. This controls the display of a vertical or horizontal rule between the buttons and the main form client area. In the image above showing the buttons, the rule is visible.

In addition, the edge spacing, control glyphs and other properties are provided. See the section ESFB Appearance in the control editor, and experiment.

Image 3

That's about it. Easiest thing to do is crank out a test project, create a form derived from ESForm, throw a few controls on it, and see what happens. I hope this code is useful to someone, please let me know what you think by providing feedback and comments.

Future Plans

  1. Optionally render a sizegrip if the form is sizeable and the buttons are docked bottom or right.
  2. Make this work with dataset linked controls - no need to hook events on those, just monitor underlying dataset modified state.
  3. Add more Designer code to effect custom property editors - pick glyphs etc.

History

Ver. 1.0.0.0 released.

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



Comments and Discussions

 
Questionwhy does apply disable OK ? Pin
The Prisoner12-Sep-06 23:15
The Prisoner12-Sep-06 23:15 
AnswerRe: why does apply disable OK ? Pin
SGarratt13-Sep-06 3:14
SGarratt13-Sep-06 3:14 
oops! that makes sense. i will effect repairs.


SGarratt

Generaltab control question Pin
The Prisoner8-Sep-06 1:19
The Prisoner8-Sep-06 1:19 
GeneralRe: tab control question Pin
The Prisoner10-Sep-06 22:49
The Prisoner10-Sep-06 22:49 
GeneralVS 2005 version Pin
The Prisoner22-Aug-06 23:47
The Prisoner22-Aug-06 23:47 
GeneralRe: VS 2005 version Pin
SGarratt24-Aug-06 1:12
SGarratt24-Aug-06 1:12 
GeneralRe: VS 2005 version Pin
The Prisoner3-Sep-06 22:41
The Prisoner3-Sep-06 22:41 
GeneralThreading Pin
Support12319-Oct-05 3:16
Support12319-Oct-05 3:16 
GeneralButto Order Pin
Erich Hohloch20-Aug-05 20:21
Erich Hohloch20-Aug-05 20:21 
GeneralRe: Butto Order Pin
SGarratt21-Aug-05 6:40
SGarratt21-Aug-05 6:40 

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.