Step 1: Identify Server Controls and Extend Common Interface
Identify all the server controls that present data for users to edit, including TextBox, DropDownList, RadioButton, CheckBox, ListBox, RadioButtonList, CheckButtonList, etc. You should also include Literal and Label controls because developers may use them to display immutable fields such as table primary keys. You could expand this list even further. For example, ASP.NET 2.0 comes with a server control called HiddenField that you might include. Developers can also include customized controls in this list by following the changes below. After identifying the server controls, you need to extend them by implementing the following interface:
Public Interface IFormGroup
Property FormGroup() As String
IFormGroup supplies the controls with a common interface (other than Control) and serves to single out grouped fields within a container easily. The FormGroup
property could be of type integer, but to make it more generic I made it a string. A FormGroup
typically corresponds to a key column of a table record. The FormGroup
value should be unique for different groups of form data. You implement the FormGroup
property following the same convention as other server control properties.
Step 2: Hook up the Value Change Event Handler
Public Property FormGroup() As String
Dim obj As Object
obj = ViewState("FormGroup")
If obj Is Nothing Then
Return CType(obj, String)
Set(ByVal Value As String)
ViewState("FormGroup") = Value
When a form field changes, the postback value change event handler, if any, will be triggered. You should exclude Literal and Label because these two controls present data in read-only fashion. The event name and argument might be different for different controls, but the body of the event handler remains unchanged; it just calls a static function called AddChangedField
is a support function responsible for recording the value change information of a control associated with a specific FormGroup
value. I'll provide more detail on the support functions in the next step. For simplicity I'll use a TextBox control as an example.
Step 3: Implement Logic to Store and Query Change Information of Form Data
Private Sub ValueChanged(ByVal sender As Object, _
ByVal args As EventArgs) Handles _
A number of functions work together to realize this technique, all of which are static, so you can bundle them into a separate FormGroup class, as seen in Listing 1
. The AddChangedField
method records field changes for its associated FormGroup. Note that if the value of FormGroup is missing (e.g. Nothing
in VB.NET), the change information will get lost because each form field must belong to a group. Other similar methods include:
- HasFormGroupChangedChecks whether any control in a form group has changed.
- HasFormGroupFieldChangedChecks if a specific form field in a form group has changed.
- FindFormGroupFieldsAn overloaded function that finds all server controls within a container that belong to the same form group.
- FindChangedFormGroupFieldsSingles out all changed fields in a group of form fields.
So where does the changed information get stored? A NameValueCollection instance records changes of all fields centrally in the global cache HttpContext.Items
is a page-level cache and accessible to all server controls. The key called $#!@FormGroup
is special and unique and should not be overridden. Each server control has a unique key as well, computed by the BuildControlKey
method based on a control's FormGroup
and the control's ID