This article is based on material originally published on DNN Developer Zone (www.dnndevzone.com). This version has been edited slightly.
Introduction
Version 4.3 of the DotNetNuke Web Application Framework introduced a suite of Property Editors. These Property Editors dynamically inject the appropriate Edit Control depending on the Data Type to be edited. There are 5 types of editor and 47 class or enum files that make up the Property Editor suite of controls. Previous articles in this series introduced the Property Editors. This article introduces the 14 EditControls included with the core distribution. Future articles in this series will describe how to create your own EditControl.
The Abstract EditControl
Figure 1: The Abstract EditControl Base Class |
|
Figure 1 shows the definition of the abstract base class EditControl. Every EditControl used by the Property Editors is derived from this base class.
Lets take a look at this abstract class. There are 9 Properties in this class and one abstract Property (StringValue).
- CustomAttributes - An array of Attributes that can be used by the derived classes to add customisation (for instance the DNNListEditControl uses the Attributes collection to determine which list to display).
- EditMode - Determines whether the control is in Edit or View mode.
- LocalResourceFile - This property is used by the EditControl to reference the current LocalResourceFile.
- Name - The name of the property being edited.
- OldValue - the old value of the property.
- Required - whether the property is required (used by drop-down lists to determine whether to add a < None Specified > option).
- StringValue - the Value expressed as a String , each derived class must override this property.
- SystemType - the underlying System.Type of the value of this control.
- Value - the value of the property.
The abstract class also defines a number of protected methods. Three methods control the rendering process.
- Render - the Render method is called by the .NET Framework at Render time and this method calls RenderEditMode or RenderViewMode to render the control, based on the value of the EditMode property.
- RenderViewMode - this method renders the control when the EditMode is set to View, as is the case in "View Profile" .
- RenderEditMode - this method renders the control when the EditMode is set to Edit, as is the case when editing a Profile. This method is shown in Listing 1 below.
Listing 1: The RenderEditMode method |
1: Protected Overridable Sub RenderEditMode(ByVal writer As HtmlTextWriter)
2: Dim propValue As String = CType(Me.Value, String)
3: ControlStyle.AddAttributesToRender(writer)
4: writer.AddAttribute(HtmlTextWriterAttribute.Type, "text")
5: writer.AddAttribute(HtmlTextWriterAttribute.Value, propValue)
6: writer.AddAttribute(HtmlTextWriterAttribute.Name, Me.UniqueID)
7: writer.RenderBeginTag(HtmlTextWriterTag.Input)
8: writer.RenderEndTag()
9: End Sub
|
These methods provide a default implementation that is called if the derived class does not provide its own rendering methods. Later in this article we will show how a derived EditControl overrides these methods. In the abstract base class a text box is rendered (an XHTML <input /> tag), the value is set to the value of the property, and the name is set to the UniqueID of the control. This last value is very important, as it is used by the .NET Framework to identify the control on PostBack.
IPostBackDataHandler Interface
If you look at Figure 1 you will see that the EditControl class implements the IPostBackDataHandler Interface. This interface provides two methods that are called automatically by the .NET Framework LoadPostData (see Listing 2) and RaisePostDataChangedEvent (see Listing 3)
Listing 2: LoadPostData method
|
1: Public Overridable Function LoadPostData(ByVal postDataKey As String, _ ByVal postCollection As NameValueCollection) As Boolean
2: Dim dataChanged As Boolean = False
3: Dim presentValue As String = CStr(Value)
4: Dim postedValue As String = postCollection(postDataKey)
5: If Not presentValue.Equals(postedValue) Then
6: Value = postedValue
7: dataChanged = True
8: End If
9: Return dataChanged
10: End Function
|
The LoadPostData method is called by the .NET Framework for any Control that implements IPostBackDataHandler. It is called just after the View State is loaded (LoadViewState) and just before the Load phase of the Control Life Cycle. The postCollection represents all the name/value pairs returned to the Server by the PostBack, and the postDataKey is the key for the current control. (Remember above when I said the UniqueID was rendered to the Name attribute of the <input/> tag). The LoadPostData method returns a boolean that lets the Framework know whether the data was changed since it was rendered.
Listing 3: The RaisePostDataChangedEvent method
|
1: Public Sub RaisePostDataChangedEvent()
2: 'Raise the DataChanged Event
3: OnDataChanged(System.EventArgs.Empty)
4: End Sub
|
Once the Load phase is complete, the .NET Framework then calls the RaisePostDataChangedEvent for every control that had previously reported that their data had changed. This allows the control to raise an event indicating its value has changed, In our case the RaisePostDataChangedEvent method calls the abstract OnDataChanged method. An abstract must be implemented in the derived class, and when the RaisePostDataChangedEvent calls the OnDataChanged method it actually calls the derived classes version, so the derived class can determine what to do next.
The base class also provides the ValueChanged event and associated OnValueChanged method (see Listing 4)
Listing 4: The Value Changed Event and the OnValueChanged Method
|
1: Public Event ValueChanged As PropertyChangedEventHandler
2:
3: Protected Overridable Sub OnValueChanged(ByVal e As PropertyEditorEventArgs)
4: RaiseEvent ValueChanged(Me, e)
5: End Sub
|
A derived class can use these events to indicated to the Editors that their values have been changed, passing the relevant information in a custom PropertyEditorEventArgs object.
Figure 2: PropertyEditorEventArgs Class
|
 |
EditControls included with DotNetNuke 4.3
As mentioned in the Introduction 14 EditControls are included with DotNetNuke (1 abstract base class and 13 derived classes). Figure 3 shows how 9 of the controls derive from the abstract base class. In general the controls can be divided into 4 groups:
- Text controls - which derive from the TextEditControl
- Integer controls - which derive from the IntegerEditControl
- True False controls - either True/False (using radio buttons) or a check Edit Control
- Lists - derived from DNNListEditControl
Figure 3: Some of the EditControls included in DotNetNuke v4.3.
|
|
The TrueFalseEditControl
As an example of a derived EditControl let's look at the TrueFalseEditControl. This control can be used to edit a boolean value using two radio buttons (True and False). As can be seen in Figure 4, this control has three properties and 2 methods.
Figure 4: The TrueFalseEditControl
|
|
The StringValue property is abstract in the base class so every derived class must implement this property.
The BooleanValue and OldBooleanValue properties are ReadOnly typed versions of the base classes Value and OldValue properties. They are not neccessary but are provided as helper properites that can be used in the methods of the class and any classes derived from it.
Listing 5: The three properties of the TrueFalseEditControl
|
1: Protected ReadOnly Property BooleanValue() As Boolean
2: Get
3: Dim boolValue As Boolean = Null.NullBoolean
4: Try
5: 'Try and cast the value to an Boolean
6: boolValue = CType(Value, Boolean)
7: Catch ex As Exception
8: End Try
9: Return boolValue
10: End Get
11: End Property
12:
13: Protected ReadOnly Property OldBooleanValue() As Boolean
14: Get
15: Dim boolValue As Boolean = Null.NullBoolean
16: Try
17: 'Try and cast the value to an Boolean
18: boolValue = CType(OldValue, Boolean)
19: Catch ex As Exception
20: End Try
21: Return boolValue
22: End Get
23: End Property
24:
25: Protected Overrides Property StringValue() As String
26: Get
27: Return BooleanValue.ToString
28: End Get
29: Set(ByVal Value As String)
30: Dim setValue As Boolean = Boolean.Parse(Value)
31: Me.Value = setValue
32: End Set
33: End Property
|
The TrueFalseEditControl overrides the RenderEditMode method of the base class as we are using two radio buttons (rather than a text box) to edit the data. This method is shown in Listing 6.
Listing 6: The RenderEditMode method of the TrueFalseEditControl
|
1: Protected Overrides Sub RenderEditMode(ByVal writer As HtmlTextWriter)
2: writer.AddAttribute(HtmlTextWriterAttribute.Type, "radio")
3: If (BooleanValue) Then
4: writer.AddAttribute(HtmlTextWriterAttribute.Checked, "checked")
5: End If
6: writer.AddAttribute(HtmlTextWriterAttribute.Value, "True")
7: writer.AddAttribute(HtmlTextWriterAttribute.Name, Me.UniqueID)
8: writer.RenderBeginTag(HtmlTextWriterTag.Input)
9: writer.RenderEndTag()
10:
11: ControlStyle.AddAttributesToRender(writer)
12: writer.RenderBeginTag(HtmlTextWriterTag.Span)
13: writer.Write("True")
14: writer.RenderEndTag()
15:
16: writer.AddAttribute(HtmlTextWriterAttribute.Type, "radio")
17: If (Not BooleanValue) Then
18: writer.AddAttribute(HtmlTextWriterAttribute.Checked, "checked")
19: End If
20: writer.AddAttribute(HtmlTextWriterAttribute.Value, "False")
21: writer.AddAttribute(HtmlTextWriterAttribute.Name, Me.UniqueID)
22: writer.RenderBeginTag(HtmlTextWriterTag.Input)
23: writer.RenderEndTag()
24:
25: ControlStyle.AddAttributesToRender(writer)
26: writer.RenderBeginTag(HtmlTextWriterTag.Span)
27: writer.Write("False")
28: writer.RenderEndTag()
29: End Sub
|
This is a much more complicated method than the one in the base class (compare with Listing 1), as it needs to render two radio buttons, and make one of them selected (or "checked") depending on the vale of the BooleanValue property. It is important to note also that the name attribute for both buttons is given the same value, the UniqueID property of the EditControl, so that the .NET Framework can correctly identify the control.
As mentioned above the RaisePostDataChangedEvent method of the base class calls the abstract OnDataChanged method, so the TrueFalseEditControl has to provide an implementation of this method. This is shown in Listing 7.
Listing 7: The OnDataChanged method of the TrueFalseEditControl
|
1: Protected Overrides Sub OnDataChanged(ByVal e As EventArgs)
2: Dim args As New PropertyEditorEventArgs(Name)
3: args.Value = BooleanValue
4: args.OldValue = OldBooleanValue
5: args.StringValue = StringValue
6: MyBase.OnValueChanged(args)
7: End Sub
|
The OnDataChanged method creates a new PropertyEditorEventArgs object, and sets its Value, OldValue and StringValue properties - the Name property is created in the constructor, and the controls Name value is passed as a parameter of the constructor.
This PropertyEditorEventArgs object is then passed to the base classes OnValueChanged method, which raises the ValueChanged event.
As can be seen from this discussion, there really isn't very much to the derived EditControls. In future articles in this series we will show how to develop new Edit Controls, and how to register them in your DotNetNuke installation.
ac7721f3-1ba6-4904-9079-c03459ec928d|1|5.0