Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / Windows Forms
Article

State Controller Component for Windows Data Entry Forms

Rate me:
Please Sign up or sign in to vote.
4.20/5 (8 votes)
18 Sep 20066 min read 50.1K   1.3K   45   13
A custom control that simplifies programming Windows data entry forms.

Introduction

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.

Properties

The control implements the IExtenderProvider interface which means that it extends properties of other controls on a form. The control provides two extended properties: StateActive and StateVisible. These properties will appear in the property drid for the extendee control with the following naming format:

StateActve on StateController1
  • The StateActivet specifies states in which an extendee control is enabled. If this property is left blank, an extendee control will not be affected when the state of a host form is changed. To set the property for a control, select the control in the designer, locate the property in the property grid, and click the down arrow. The state picker comes up, see below:

    State Picker

    In the state picker, tick the states in which the control should be enabled.

  • The StateVisible specifies states in which an extendee control is visible.

The control also provides its own properties:

  • The 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.
  • The CurrentState returns the name of the current state of the control.

Method

  • The 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.

Event

  • The 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 IExtenderProvider and 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.

C#
[ToolboxBitmap(typeof(StateController))]
[ProvideProperty("StateActive", typeof(Control)), 
ProvideProperty("StateVisible", typeof(Control)), 
Designer(typeof(StateControllerDesigner)),
DefaultEvent("StateChanged"),
ToolboxItemFilter("System.Windows.Forms")]
public class StateController : System.ComponentModel.Component, 
                               IExtenderProvider, ISupportInitialize

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.

The 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.

C#
public bool CanExtend(object extendee)
{
    return ((extendee is Control) && !(extendee is Form));
}

When implementing IExtenderProvider, we need to create a pair of public methods for each extended property. These methods must be named Get<PropertyName> and Set<PropertyName>. These methods act like get/set parts of a regular property.

The GetStateActive and SetStateActive methods support the StateActive property, and respectively GetStateVisible and SetStateVisible methods support the StateVisible property.

C#
[Description("Retrieve Active States descriptors for a control"), 
Category("StateManagment"),Localizable(true),
Editor(typeof(SelectedStatesEditor), 
       typeof(System.Drawing.Design.UITypeEditor))]
public virtual string GetStateActive(Control ctl)
{
    return (string) this.m_activeStates[ctl];
}

public virtual void SetStateActive(Control ctl,string value)
{
    if (this.DesignMode) 
    {
        if (value!=null)
        {
            // remove blanks if any
            this.CleanInput(ref value);
            if (!CheckValue(value))
            // Validate user's input
                throw new ArgumentException("Invalid value " + 
                                            value);
            }
        }
        if (value!=null)
            this.m_activeStates[ctl] = value;
        else
            this.m_activeStates.Remove(ctl);
}

The pair of methods ShouldSerialize<PropertyName> and Reset<PropertyName> prevent the serialization of empty values of the extended properties in the form’s code.

C#
private bool ShouldSerializeStateActive(Control ctrl)
{
    if ((this.m_activeStates[ctrl] == null) || (
        ((string)this.m_activeStates[ctrl]).Length == 0))
        return false;
            
    return true;
}

private void ResetStateActive(Control ctrl)
{
    this.SetStateActive(ctrl, "");
}

The 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.

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


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVB source missing Pin
AxelM27-Sep-06 20:26
AxelM27-Sep-06 20:26 
GeneralRe: VB source missing Pin
Sergey O28-Sep-06 3:20
Sergey O28-Sep-06 3:20 
GeneralRe: VB source missing Pin
AxelM28-Sep-06 4:59
AxelM28-Sep-06 4:59 
QuestionA Problem Pin
fandy20-Sep-06 16:10
fandy20-Sep-06 16:10 
AnswerRe: A Problem Pin
Sergey O20-Sep-06 23:21
Sergey O20-Sep-06 23:21 
GeneralRe: A Problem Pin
fandy20-Sep-06 23:57
fandy20-Sep-06 23:57 
GeneralRe: A Problem Pin
Sergey O21-Sep-06 1:18
Sergey O21-Sep-06 1:18 
GeneralRe: A Problem Pin
fandy24-Sep-06 16:39
fandy24-Sep-06 16:39 
GeneralRe: A Problem Pin
Sergey O25-Sep-06 2:05
Sergey O25-Sep-06 2:05 
GeneralRe: A Problem Pin
fandy26-Sep-06 20:15
fandy26-Sep-06 20:15 
GeneralRe: A Problem Pin
Sergey O26-Sep-06 23:15
Sergey O26-Sep-06 23:15 
GeneralRe: A Problem Pin
fandy26-Sep-06 23:47
fandy26-Sep-06 23:47 
GeneralGreat tool and perfect timing Pin
MightyMart19-Sep-06 3:10
MightyMart19-Sep-06 3:10 

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.