Home arrow ASP.NET arrow Page 3 - An Object Driven Interface with .Net
ASP.NET

An Object Driven Interface with .Net


Using .Net, Paul will demonstrate how to generate an object driven interface. A rich source of support material is included with this article so you can start building interfaces today.

Author Info:
By: Paul Stevens
Rating: 5 stars5 stars5 stars5 stars5 stars / 42
August 24, 2003
TABLE OF CONTENTS:
  1. · An Object Driven Interface with .Net
  2. · Part 2: Creating our Business Object
  3. · Part 3: The Interface Generator
  4. · Part 4: Using our Interface Generator

print this article
SEARCH DEVARTICLES

An Object Driven Interface with .Net - Part 3: The Interface Generator
(Page 3 of 4 )

Our Interface Generator is going to generate an interface based on our business object, I decided to create an interface based on the Visual Studio .NET Property Grid since this control does something very similar to what we are doing in this exercise, however to make it interesting we are going to create a Server Side ASP.Net Web Control.

An example of what our interface will look like.

One of the first things we need to do especially based on the fact that we are creating a web control is take into account two things, 1. We want to be able to retrieve the values the user has entered into the interface, and 2. The controls we are interested in are probably going to be deeply nested within other controls on our web page making it extremely difficult to find them again. For Example based on our Business Class and the interface you can see above, The Control Containing the value for City will be nested as follows

    Base Control
        |----Table1
        |----Table2
        |----Div1
        |            |----Table3
        |----Table4
        |----Div2
        |            |----Table5
                      |----Row1
                      |----Row2
                      |----Row3
                                  |----Cell1
                                  |----Cell2
                                  |----Cell3
                                              |----City

Therefore to get at this control first you need to know exactly where it is and second you need to type something like this Control = Base.Controls(5).Controls(1).Rows(3).Cells(3).Controls(1) just to get to it, to make this a little easier we are going to create a structure that we can use to store a pointer to our control, and some information about the property this control is attached to.

Public Structure fieldContainer
Public name As String
Public field As System.Web.UI.Control
Public fieldType As Type
Public propertyType As Type
End Structure

The above structure lets us store a pointer to our controls, the name of the property this control is attached to, the type of field control it’s using such as System.Web.UI.Webcontrols.Textbox and the type of the property such as System.String.

<ToolboxData("<{0}:InterfaceGenerator runat=server></{0}:InterfaceGenerator>")> _
Public Class InterfaceGenerator
Inherits System.Web.UI.WebControls.WebControl
...
End Class

the code declaration above creates a class that inherits from System.Web.UI.WebControls.WebControl to create our custom control, and uses the ToolboxData attribute to specify the way the control is rendered in the Designer at design time, the attributes above result in Runtime HTML Designer Code similar to the code below where cc1 is the tagprefix declared in the reference code.

<cc1:InterfaceGenerator id="Interfacegenerator2" runat="server"></cc1:InterfaceGenerator>

once we have created the class for our interface designer we now need to start creating our interface, firstly our control can do nothing if an instance of a business object is not passed to it, so we start by creating a New Constructor that has a required parameter WizardObject as type Object.

<ToolboxData("<{0}:InterfaceGenerator runat=server></{0}:InterfaceGenerator>")> _
Public Class InterfaceGenerator
Inherits System.Web.UI.WebControls.WebControl
...
Public Sub New(ByVal WizardObject As Object)
...
End Sub
...
End Class

We are going to be using a resource file in which we will be storing some style information and also a few lines of javascript which we want to add to our interface when it’s generated, this style info and javascript will help us in creating an interactive and usable user interface.

<ToolboxData("<{0}:InterfaceGenerator runat=server></{0}:InterfaceGenerator>")> _
Public Class InterfaceGenerator
Inherits System.Web.UI.WebControls.WebControl
...
Public Sub New(ByVal WizardObject As Object)
rm = New ResourceManager("Wizard.Control.Prototype.InterfaceGenerator", _ System.Reflection.Assembly.GetExecutingAssembly())
...
End Sub
...
End Class

Our resource manager points to the emebeded resource InterfaceGenerator in the Wizard.Control.Prototype Namespace in the currently executing assembly. In the general declarations part of our control we will start by declaring a couple of controls that we can reuse, these controls are going to be used to build our interface, by using them we will dynamically add controls to the interface. The following lines are declared form part of the declaration section

Private section As Panel
Private mainTable As Table
Private lbl As WebControls.Label
Private row As TableRow
Private cell As TableCell
Private subTable As Table
Private subRow As TableRow
Private subCell As TableCell
Private im As Image
Private link As HtmlControls.HtmlAnchor

We will also need somewhere to store the object that gets passed to us.

Private lWizardObject As Object

When the control is initialized and the object passed to us we will use reflection to retrieve type information obout the object and a list of the Public properties in the control.

Public Sub New(ByVal WizardObject As Object)
...
lWizardObject = WizardObject
myType = WizardObject.GetType
myPropertyInfo = myType.GetProperties(BindingFlags.Public Or
BindingFlags.Instance Or BindingFlags.DeclaredOnly)
End Sub

The binding flags in the GetProperties Statement specify that “BindingFlags.Public” Only public properties should be returned, “BindingFlags.Instance” Only Non Static members should be returned and “BindingFlags.DeclaredOnly” only return properties declared in the object and not any that it may have inherited from a base class, such as the list property our object inherited from our base class.

Once we have done these basic tasks, we can now start to generate our interface.

Public Sub New(ByVal WizardObject As Object)
...
'We start by creating a new table object to contain all our controls
'and to allow us to place controls on the screen
mainTable = New Table
mainTable.ID = "MainTable"
mainTable.Width = Unit.Percentage(100)
mainTable.Height = Unit.Percentage(100)
mainTable.CellPadding = 0
mainTable.CellSpacing = 0
mainTable.BorderWidth = Unit.Pixel(0)
'Create the first row and cell that will contain all our
'interface objects
row = New TableRow
cell = New TableCell
cell.VerticalAlign = VerticalAlign.Top
'the sub Table will create our first "panel" at the top of the form
'that contains he image
subTable = New Table
subTable.CellPadding = 0
subTable.CellSpacing = 0
subTable.BorderWidth = Unit.Pixel(0)
subTable.Width = Unit.Percentage(100)
subTable.ID = "SubTable1"
subRow = New TableRow
subCell = New TableCell
subCell.ColumnSpan = 3
subCell.CssClass = "header"
im = New Image
im.ImageUrl = "images/categorized.gif"
subCell.Controls.Add(im)
subRow.Cells.Add(subCell)
subTable.Rows.Add(subRow)
cell.Controls.Add(subTable)
'because we do not have a predefined list of categories
'we will loop through each property's attributes and create
'a list of all the Sections that we want to create
For i As Int16 = 0 To myPropertyInfo.Length - 1
'First we get the property's details from our list of
'properties
Dim myPropInfo As PropertyInfo = CType(myPropertyInfo(i), PropertyInfo)
'we the get a list of all the attributes that have been attached to
'the property since there may be more than one and
'we might not be interested in some of them
Dim attributes As Object() = myPropInfo.GetCustomAttributes(False)
Dim attribute As WizardAttributes
For s As Int16 = 0 To attributes.Length - 1
'looping through the attributes, we check to see if any of
'them are of the Type WizardAttribute as this is the one we
'are interested in
If TypeOf attributes(s) Is WizardAttributes Then
'if we find it we use directcast to cast it from type Object
'to type WizardAttribute, and stuff it into our Variable called
'Attribute an use attribute to add the sectionname to our list
'of sections.
attribute = DirectCast(attributes(s), WizardAttributes)
If Sections.Contains(attribute.SectionName) = False Then
Sections.Add(attribute.SectionName, fields)
End If
End If
Next
Next
'We create our Style and script sections for our control
CreateStyle()
CreateScripts()
'now that we have a list of sections,
'we can start to create each of them
Dim SectionName As String
For Each SectionName In Sections.Keys
CreateSection(SectionName)
Next
'with our sections and fields added to the interface
'we can create our help section that sits at the bottom of the screen
'an finally add the whole lot to our control's control collection
CreateHelpSection()
mainTable.Rows.Add(row)
Controls.Add(mainTable)
End Sub

In the code above, we start by creating the table that will contain our controls and allow us to do some nice layout on the screen; we create the topmost panel of our screen that contains the toolbar graphic.

This is currently nothing but a graphic and we might want to do something with it later on, we then loop through all of our properties and reach the attributes that belong to each in order to build a list of the sections that our interface will contain. Each of these sections is collapsible and allows us to group relevant data.

We then call two functions that we use to add the style information and JavaScript that we need to our interface.

Private Sub CreateScripts()
Dim ScriptCode As String = rm.GetString("Scripts")
Dim Literal As New WebControls.Literal
Literal.Text = ScriptCode
Controls.Add(Literal)
End Sub
Private Sub CreateStyle()
Dim StyleCode As String = rm.GetString("Style")
Dim Literal As New WebControls.Literal
Literal.Text = StyleCode
Controls.Add(Literal)
End Sub

The two methods both use our resource manager to populate a string with the text stored in our resource file relevant to each method and uses a literal Control to add this text to our interface.

After that we loop through each of the sections in our list and start to create them.

...
For Each SectionName In Sections.Keys
CreateSection(SectionName)
Next
...

To create each section we pass the createSection Method the Section Name that it will use to create the section header and determine which properties should be rendered under it.

Private Sub CreateSection(ByVal SectionName As String)
' we start by creating the table that will be used to render
' our sections heading and Expand/Collapse Button
subTable = New Table
subTable.CellPadding = 0
subTable.CellSpacing = 0
subTable.BorderWidth = Unit.Pixel(0)
subTable.Width = Unit.Percentage(100)
subTable.ID = SectionName
subRow = New TableRow
subCell = New TableCell
subCell.ColumnSpan = 3
subCell.CssClass = "category"
'the link that we add here expands and collapses
'our Section, the way this is achieved is by hosting the actual
'sections controls in a <DIV> which is shown and hidden with the use
'of some javascript
link = New HtmlControls.HtmlAnchor
link.HRef = "javascript:toggleCategory(document.getElementById('cat" & SectionName & "'), document.images('t" & SectionName & "'))"
link.Attributes.Add("onmouseover", "window.status='Toggle Category'; return true")
link.Attributes.Add("onmouseout", "window.status=''; return true")
link.Attributes.Add("onfocus", "this.blur()")
im = New Image
im.ImageUrl = "images/head-.gif"
im.ID = "t" & SectionName
link.Controls.Add(im)
subCell.Controls.Add(link)
lbl = New Label
lbl.Text = " " & SectionName
subCell.Controls.Add(lbl)
subRow.Cells.Add(subCell)
subTable.Rows.Add(subRow)
cell.Controls.Add(subTable)
'once we have created or section Header we move on to create the fields
'that the section contains
CreateSectionFields(SectionName)
row.Cells.Add(cell)
mainTable.Rows.Add(row)
End Sub

The Create Section Method creates a Table that is used to render the actual section header that contains a Collapse and expand button and the sections name, the CreateSection method in turn calls CreateSectionFields.

Private Sub CreateSectionFields(ByVal SectionName As String)
'We start by declaring the "gutter" or the indentation on the
'left, this is a variable on its own since we will later use it
'to contain our validation controls.
Dim gutter As TableCell
'this is where we create the actual section it exists out of a
'Panel "Rendered as a <DIV>" that contains a table which contains
'our interface controls
section = New Panel
section.ID = "cat" & SectionName
'Here we create the table that will contain each of the controls
subTable = New Table
subTable.CellPadding = 0
subTable.CellSpacing = 0
subTable.BorderWidth = Unit.Pixel(0)
subTable.Width = Unit.Percentage(100)
fields = New System.Collections.ArrayList
For i As Int16 = 0 To myPropertyInfo.Length - 1
Dim myPropInfo As PropertyInfo = CType(myPropertyInfo(i), PropertyInfo)
Dim attributes As Object() = myPropInfo.GetCustomAttributes(False)
Dim attribute As WizardAttributes
For s As Int16 = 0 To attributes.Length - 1
If TypeOf attributes(s) Is WizardAttributes Then
attribute = DirectCast(attributes(s), WizardAttributes)
Exit For
End If
Next
'We will start by looping through each property in our list
'and checking whether they belong to the current Section
If attribute.SectionName = SectionName Then
'if the property does belong to the current section
'we create a row in our table for it
subRow = New TableRow
gutter = New TableCell
gutter.Width = Unit.Parse(15)
gutter.CssClass = "gutter"
gutter.VerticalAlign = VerticalAlign.Middle
gutter.HorizontalAlign = HorizontalAlign.Center
subRow.Cells.Add(gutter)
subCell = New TableCell
subCell.CssClass = "cell"
subCell.Text = attribute.Label
subRow.Cells.Add(subCell)
subCell = New TableCell
subCell.CssClass = "inputcell"
'the inputcontrol was declared earlier as an object since it could be any
'Web or HTML Control
'we will now use reflection to create an instance of a control as specified
'in the property's attributes
inputControl = Activator.CreateInstance(attribute.Type)
'because we have no idea exactly what kind of control we are working with
'we use some generic methods such as Style.Add and Attributes.Add to
'add all the necessary styles and attributes to our control.
'this includes an
'onfocus event that calls client side Javascript to display help
'information
inputControl.Style.Add("width", "98%")
inputControl.Style.Add("border-style", "None")
inputControl.Style.Add("border-width", "0pt")
inputControl.Style.Add("height", "100%")
inputControl.Attributes.Add("Class", "cell")
inputControl.Attributes.Add("onfocus", "doHelp(this)")
inputControl.ID = myPropInfo.Name
inputControl.Attributes.Add("help","<b>" & attribute.Label & _
"</b><br><br>" & Microsoft.VisualBasic.IIf(attribute.HelpText = "", _
"<BR>", attribute.HelpText))
'because we still don’t really know which control
'we, have we use the following if statement
'to look for a property we can use to display the property's
'current value to the user. this could have been don with a select case
'or a loop that checks each control against ours and
'then casts our control to the correct type where we can then use the
'correct and known property or method to set the value however there are
'about 5 (I Might have missed one or two) possible properties and many more
'possible controls.
'We then use reflection to call Get Property for our object properties
'and use the returned value to populate the relevant property of the
'control
If Not attribute.Type.GetProperty("Checked", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
inputControl.Checked = _
myType.InvokeMember(myPropInfo.Name, BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {})
ElseIf Not attribute.Type.GetProperty("Text", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
inputControl.Text = _
myType.InvokeMember(myPropInfo.Name, BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {})
ElseIf Not attribute.Type.GetProperty("SelectedValue", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
If attribute.ListIndex > -1 Then
' in the case of a list control we use reflection to retirve the list as
'specified by the ListIndex attribute, and then use this collection
' to populate the list control with the specified items
Dim listCollection As System.Collections.Specialized.StringCollection
listCollection = _
myType.InvokeMember("List", BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {attribute.ListIndex})
Dim item As String
For Each item In listCollection
inputControl.Items.Add(item)
Next
End If
'we also select the item in the list
'as specified by the SelectedIndex attribute
'or set the selectedValue to the value of the Property
If attribute.SelectedIndex > -1 Then
inputControl.SelectedIndex = attribute.SelectedIndex
Else
inputControl.SelectedValue = _
myType.InvokeMember(myPropInfo.Name, BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {})
End If
ElseIf Not attribute.Type.GetProperty("Value", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
inputControl.Value = _
myType.InvokeMember(myPropInfo.Name, BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {})
ElseIf Not attribute.Type.GetProperty("InnerText", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
inputControl.InnerText = _
myType.InvokeMember(myPropInfo.Name, BindingFlags.GetProperty, _
Nothing, lWizardObject, New Object() {})
End If
'if the Locked attribute = True then we disable the
'control
If attribute.Locked = True Then
inputControl.Attributes.Add("disabled", "disabled")
End If
'Here we use the structure we created at the start
'to store a pointer to our control so that we can retrieve it easily
'and some information about the property
Dim field As New fieldContainer
field.name = myPropInfo.Name
field.field = inputControl
field.fieldType = inputControl.GetType
field.propertyType = myPropInfo.PropertyType
fields.Add(field)
'if the Required attribute = True, we add a RequiredFieldValidator
'to the "gutter"
If attribute.Required = True Then
Dim validator As New WebControls.RequiredFieldValidator
validator.Text = "*"
validator.Style.Add("CURSOR", "help")
validator.ToolTip = "This is a required field"
validator.Attributes.Add("help", "<b>" & attribute.Label & "</b><br><br>" & validator.ToolTip)
validator.Attributes.Add("onclick", "doHelp(this)")
validator.ControlToValidate = inputControl.id
validator.Font.Size = FontUnit.Parse("11px")
validator.Font.Name = "Arial"
gutter.Controls.Add(validator)
End If
' if our poperty is a numeric property and has no validation details
'specified in the attributes thena we add a default
'Regex Validator that only allows numbers, if it is not a numeric property
' but does have a Validation Expression specified we will add the relevant
'validator to the "gutter"
If myPropInfo.PropertyType Is GetType(System.Decimal) Or _
myPropInfo.PropertyType Is GetType(System.Int16) Or _
myPropInfo.PropertyType Is GetType(System.Int32) Or _
myPropInfo.PropertyType Is GetType(System.Int64) Or _
myPropInfo.PropertyType Is GetType(System.Double) Or _
myPropInfo.PropertyType Is GetType(System.Byte) Or _
myPropInfo.PropertyType Is GetType(System.Single) _
Then
Dim ValidationMessage As String = _
Microsoft.VisualBasic.IIf(attribute.ValidationText = "", "Not valid for this field", attribute.ValidationText)
Dim validator As New WebControls.RegularExpressionValidator
validator.Text = "*"
validator.Style.Add("CURSOR", "help")
validator.ControlToValidate = inputControl.ID
validator.Font.Size = FontUnit.Parse("11px")
validator.Font.Name = "Arial"
If attribute.ValidationExpression = "" Then
validator.ValidationExpression = "[0-9]{1,}[.]{0,1}[0-9]{0,}"
validator.ToolTip = "Only Numeric Values ex. 1.0, 0.3, 12.09872 are allowed"
Else
validator.ValidationExpression = attribute.ValidationExpression
validator.ToolTip = ValidationMessage
End If
validator.Attributes.Add("help", "<b>" & attribute.Label & "</b><br><br>" & validator.ToolTip)
validator.Attributes.Add("onclick", "doHelp(this)")
gutter.Controls.Add(validator)
ElseIf Not attribute.ValidationExpression = "" Then
Dim ValidationMessage As String = _
Microsoft.VisualBasic.IIf(attribute.ValidationText = "", "Not valid for this field", attribute.ValidationText)
Dim validator As New WebControls.RegularExpressionValidator
validator.Text = "*"
validator.Style.Add("CURSOR", "help")
validator.ValidationExpression = attribute.ValidationExpression
validator.ToolTip = ValidationMessage
validator.Attributes.Add("help", "<b>" & attribute.Label & "</b><br><br>" & validator.ToolTip)
validator.Attributes.Add("onclick", "doHelp(this)")
validator.ControlToValidate = inputControl.ID
validator.Font.Size = FontUnit.Parse("11px")
validator.Font.Name = "Arial"
gutter.Controls.Add(validator)
End If
'add the control to the table
subCell.Controls.Add(inputControl)
subRow.Cells.Add(subCell)
'add the field to the Table
subTable.Rows.Add(subRow)
End If
Next
'add the fields to the section
section.Controls.Add(subTable)
cell.Controls.Add(section)
End Sub

In the CreateSectionFields Method we perform a few tasks, first we create a gutter or indentation on the left hand side of the screen so that the section fields are all slightly indented from the section header, we will later use this cell in the table to host our Validation controls. We then create the actual section a panel control that will contain the table containing our interface controls, the reason for the panel control is that it is rendered as a <DIV> by ASP.NET and can the be used to hide or show it’s contents, thereby expanding and collapsing each Section.

Inside the section we create a table to contain all our controls and supply us with a way to do some layout on the screen. The “inputcontrol” that we declared as an Object earlier is now used to cerate our Web or HTML Controls, using reflection we create an instance of the Type specified in the Property’s attributes, and then add some style information and attributes to the control on of these attributes includes an event declaration that calls a JavaScript Function that displays context sensitive help to the user.

We then determine whether the control has a property that we can use to display the property’s current value to the user and if so we use reflection the Call the Get method of our property and use the returned value to populate the controls relevant property.

Once we have done this we add create an instance of our Field Container structure, add a pointer to the field and some other relevant information to it and add it to our collection of Field Containers, we will later use these field containers to retrieve the values from our interfaces controls and update the values of the Objects Properties.

Once this is done we add the relevant validation controls to our interface to ensure that what the user enters in the interface can be used by the relevant properties, and add the fields to the section and the section to the Controls, Controls Collection.

What’s worth noticing in this method is the use of reflection to create objects, and read property Values an the customization of the validation controls with the use off attributes allowing us to display the validation message in our context sensitive help section.

After the CreateSectionFields Function has been called for each of the relevant properties and all of the sections have been created. A call is made to “CreateHelpSection”

Private Sub CreateHelpSection()
'CreateHelpSection Create a Final Section at the bottom of the page
'that will be used to render context sensitive help
row = New TableRow
row.Height = Unit.Percentage(100)
cell = New TableCell
cell.VerticalAlign = VerticalAlign.Bottom
cell.Height = Unit.Percentage(100)
subTable = New Table
subTable.CellPadding = 5
subTable.CellSpacing = 0
subTable.BorderWidth = Unit.Point(0)
subTable.Width = Unit.Percentage(100)
subTable.Height = Unit.Percentage(100)
subRow = New TableRow
subRow.Height = Unit.Percentage(100)
subCell = New TableCell
subCell.Text = " "
subRow.Cells.Add(subCell)
subTable.Rows.Add(subRow)
subRow = New TableRow
subCell = New TableCell
subCell.Style.Add("BORDER-TOP", "#808080 1px solid")
Dim HelpTable As New Table
HelpTable.CellPadding = 3
HelpTable.CellSpacing = 0
HelpTable.BorderWidth = Unit.Point(0)
HelpTable.Width = Unit.Percentage(100)
HelpTable.CssClass = "footer"
Dim helprow As New TableRow
Dim helpcell As New TableCell
helpcell.CssClass = "help"
helpcell.VerticalAlign = VerticalAlign.Top
helpcell.Style.Add("BORDER", "#808080 1px solid")
Dim helpContainer As New Label
helpContainer.ID = "helpText"
helpContainer.Text = "<b>Help</b><br><br><br>"
helpContainer.Style.Add("HIEGHT", "60px")
helpcell.Controls.Add(helpContainer)
helprow.Cells.Add(helpcell)
HelpTable.Rows.Add(helprow)
subCell.Controls.Add(HelpTable)
subCell.CssClass = "footer"
subRow.Cells.Add(subCell)
subTable.Rows.Add(subRow)
subRow = New TableRow
subCell = New TableCell
subCell.CssClass = "footer"
subCell.HorizontalAlign = HorizontalAlign.Right
subCell.Height = Unit.Point(10)
Dim reset As New HtmlControls.HtmlInputButton
reset.Attributes.Add("type", "reset")
reset.Attributes.Add("value", "Reset")
reset.ID = "reset1"
subCell.Controls.Add(reset)
subCell.Controls.Add(New LiteralControl(" "))
submit = New WebControls.Button
submit.Text = "Submit"
submit.ID = "submit1"
AddHandler submit.Click, AddressOf SubmitDetail
subCell.Controls.Add(submit)
subRow.Cells.Add(subCell)
subTable.Rows.Add(subRow)
cell.Controls.Add(subTable)
row.Cells.Add(cell)
End Sub

“CreateHelpSection” creates the section at the very bottom of the page where context sensitive help is displayed to the user and the Reset and Submit buttons are rendered.

And that’s it the code above is all we need to create an attributes class, create a Business object that uses these attributes and an interface generator that uses reflection and the attributes to generate a useable interface, however the interface may be useable but It’s not useful until we can get values back from it and populate our objects properties with the changes the user has made.

For this we first need a way to get the object we handed to the interface generator back when it’s been updated, for that we will create a property

Property WizardObject() As Object
Get
Return lWizardObject
End Get
Set(ByVal Value As Object)
lWizardObject = Value
End Set
End Property

Once we have the property we can get the object back but we still need a way to update it, this is again where reflection comes in handy, in the CreateHelpSection Method we created a Submit button and added an event handler to its Click event this will allow us to trap the submit of the form and update our objects properties.

...
submit = New WebControls.Button
submit.Text = "Submit"
submit.ID = "submit1"
AddHandler submit.Click, AddressOf SubmitDetail
subCell.Controls.Add(submit)
...

the submitDetail event Handler allows us to capture the forms submit and use the controls on the form to update our object and in turn raises an event that lets us know the objects values have been updated.

Private Sub SubmitDetail(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim value As Object
Dim field As Object
Dim cfield As fieldContainer
For Each fields In Sections.Values
For Each cfield In fields
field = cfield.field
If Not cfield.fieldType.GetProperty("Checked", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
value = field.Checked
value = Convert.ChangeType(value, cfield.propertyType)
myType.InvokeMember(cfield.name, BindingFlags.SetProperty, _
Nothing, lWizardObject, New Object() {CBool(value)})
ElseIf Not cfield.fieldType.GetProperty("Text", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
value = field.Text
value = Convert.ChangeType(value, cfield.propertyType)
myType.InvokeMember(cfield.name, BindingFlags.SetProperty, _
Nothing, lWizardObject, New Object() {value})
ElseIf Not cfield.fieldType.GetProperty("SelectedValue", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
value = field.SelectedValue
value = Convert.ChangeType(value, cfield.propertyType)
myType.InvokeMember(cfield.name, BindingFlags.SetProperty, _
Nothing, lWizardObject, New Object() {value})
ElseIf Not cfield.fieldType.GetProperty("Value", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
value = field.Value
value = Convert.ChangeType(value, cfield.propertyType)
myType.InvokeMember(cfield.name, BindingFlags.SetProperty, _
Nothing, lWizardObject, New Object() {value})
ElseIf Not cfield.fieldType.GetProperty("InnerText", BindingFlags.Public Or BindingFlags.Instance) Is Nothing Then
value = field.InnerText
value = Convert.ChangeType(value, cfield.propertyType)
myType.InvokeMember(cfield.name, BindingFlags.SetProperty, _
Nothing, lWizardObject, New Object() {value})
End If
Next
Next
RaiseEvent ValuesUpdated(lWizardObject, Nothing)
End Sub

Since we added all our controls to the field containers earlier we can now simply loop through each of these and retrieve their values. Using reflection we then call the Set Method of the relevant properties to update their values and raises an event to let us know the values have been updated.

That’s it we now have a way to return the new and updated object that we can then use to do whatever needs to be done.

Now we need to use our nice new interface generator.


blog comments powered by Disqus
ASP.NET ARTICLES

- How Caching Means More Ca-ching, Part 2
- How Caching Means More Ca-ching, Part 1
- Reading a Delimited File Using ASP.Net and V...
- What is .Net and Where is ASP.NET?
- An Object Driven Interface with .Net
- Create Your Own Guestbook In ASP.NET
- HTTP File Download Without User Interaction ...
- Dynamically Using Methods in ASP.NET
- Changing the Page Size Interactively in a Da...
- XML Serialization in ASP.NET
- Using Objects in ASP.NET: Part 1/2
- IE Web Controls in VB.NET
- Class Frameworks in VB .NET
- Cryptographic Objects in C#: Part 1
- Sample Chapter: Pure ASP.Net

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials