Many people think of programming data entry forms as very boring activity. I think so too. But sometimes I feel that something must be done to make this job easier. So I’ve developed this control to simplify designing and programming data entry forms.
Data entry forms are associated with documents, and enable the user to perform operations on associated documents, usually, operations such as creating, viewing, editing, and searching of documents. At any given time, a data entry form can be in one of several pre-defined states, depending on the operation that the user is currently performing. While designing a data entry form, the developer defines states which the form will maintain, and programs the logic that sets the form to a particular state in response to the user’s interaction. Say the user selects a menu option or clicks a button to enter a new document. When a form is set to a new state, some of its controls are enabled (become active) to process the user’s input while other controls are disabled. In some cases, programming such logic is not as simple as it seems. We need to take into account such factors as the document status, the user’s privileges and so on to give the user the access to only certain fields on a form. The State Controller provides design-time support for specifying the states for each control on a form in which this control is enabled, and/or states in which the control is visible. The State Controller also provides a method that sets a host form to the specified state at runtime.
Using the code
In order to use this control, while in design mode, you need to install it on the VS toolbox. To do that, select a tab you want to add this control to, right-click somewhere in your toolbox, and select "Add/Remove Items...", then navigate to the location of the StateController.DLL, select the DLL, and click OK. After that the control should be in your toolbox.
The control implements the
IExtenderProvider interface which means that it extends properties of other controls on a form. The control provides two extended properties:
StateVisible. These properties will appear in the property drid for the extendee control with the following naming format:
StateActve on StateController1
The control also provides its own properties:
Items property contains a reference to the list of states defined for the host form. A collection editor is associated with this property. This editor allows you to create and edit individual members of a collection. When adding a new state, you need to specify a state name, and optionally, a control on a form that receives focus when the form is set to this state.
CurrentState returns the name of the current state of the control.
SetState is an overloaded method that sets a host form to the specified state. This method takes the state name as a parameter. The overloaded version accepts the second parameter which specifies a control that receives the focus when a new state is activated. If there is no state in the control’s state collection with the specified name, an
ArgumentException is thrown.
StateChanged is raised when the control is set to a new state.
I created a demo project to show how this control can be used. The demo includes a data entry form that maintains the Customer table from the Northwind database. This form supports basic operations on the table – adding, editing, viewing, and searching records. I also wanted to demonstrate how to use this control to permit only users with certain privileges to have access to some fields. In this case, a user with super-user privileges can see the customer balance and edit the value of the Credit Limit field. So I defined the following states for this form:
Idle – in this state, the current record of the table is shown, and the form waits for the user to make the choice.
New - in this state, a new record is being entered.
Edit - the state for editing an existing record.
Search - this state permits the user to search a record in the table.
Idle SuperUser - show the current record when the user has super-user privileges.
Edit SuperUser – - edit record by the user with the super-user privileges.
The form is set to a new state in response to user interaction. The
SetState method is invoked within even handlers to set the form to an appropriate state. I think the source code gives you some ideas on how to use this control. I tried to make the demo as simple as possible.
Points of interest
The control is a subclass of the
Component class, and implements the
ISupportInitialize interfaces. I chose the implementation of the
ISupportInitialize interface just not to check properties when the control is loading in the Windows Forms designer.
public class StateController : System.ComponentModel.Component,
Two hash tables are used to stash the values of the properties extended for the form’s controls. The reference to a control is used as the key for the hash table entry, and the value of the property is stored in the value part of the hash table entry.
CanExtend method specifies what types of extendee controls are supported by the
StateController. In this case, all controls derived from the control class, except forms, are supported.
public bool CanExtend(object extendee)
return ((extendee is Control) && !(extendee is Form));
IExtenderProvider, we need to create a pair of public methods for each extended property. These methods must be named
Set<PropertyName>. These methods act like get/set parts of a regular property.
SetStateActive methods support the
StateActive property, and respectively
SetStateVisible methods support the
[Description("Retrieve Active States descriptors for a control"),
public virtual string GetStateActive(Control ctl)
return (string) this.m_activeStates[ctl];
public virtual void SetStateActive(Control ctl,string value)
throw new ArgumentException("Invalid value " +
this.m_activeStates[ctl] = value;
The pair of methods
Reset<PropertyName> prevent the serialization of empty values of the extended properties in the form’s code.
private bool ShouldSerializeStateActive(Control ctrl)
if ((this.m_activeStates[ctrl] == null) || (
((string)this.m_activeStates[ctrl]).Length == 0))
private void ResetStateActive(Control ctrl)
SetState method sets a host form to the state specified by the first parameter. It makes two loops. In the first loop, the controls of the host form are enabled or disabled depending on the value of the
StateActive property for a control. The second loop analyzes the values of the
StateVisible property, and hides or shows controls.
The assembly contains the control class itself and auxiliary classes – type converters, UI editors, a control designer which facilitates the design-time behavior of the control, and the serialization of the control’s properties in the form code. Actually, I spent 90% of my time on programming and debugging these editors and converters.