Dynamically creating forms in ASP.NET 2
For those of us who'd rather write code than dragging and dropping controls on a form, here comes a few pointers:
1) Always create all controls of all possible views
Even if you don't want to display all dynamically created controls, you will need to create them, if you would like to benefit from ASP.NET's built-in ViewState capability. That said, you don't have to display or even populate (see point 2 below) all controls. Just create them. Then, if you don't want them after all, set their Visible flag to False.
2) Don't databind controls on postback.
A common mistake when dynamically creating pages, is to attempt to databind on callback. Well,m the thing is that the control is already bound, sort of speak. The data you are trying to bind is already in the control's view state, isn't it? ;-)
3) Create a FormBuilder class
Save yourself some time. Here's a sample FormBuilder (written in VB.NET becuase I get paid for it ;-)):
Public Class FormBuilder
Private m_strLabelCssClass As String = "inputField"
Private m_ctlPublisher As Control
Private m_ctlSeparator As Control = Nothing
Private m_unitLabelColumnWidth As Unit
Public Property LabelCssClass() As String
Get
Return m_strLabelCssClass
End Get
Set(ByVal value As String)
m_strLabelCssClass = value
End Set
End Property
Public Property Publisher() As Control
Get
Return m_ctlPublisher
End Get
Set(ByVal value As Control)
m_ctlPublisher = value
End Set
End Property
Public Property LabelColumnWidth() As Unit
Get
Return m_unitLabelColumnWidth
End Get
Set(ByVal value As Unit)
m_unitLabelColumnWidth = value
End Set
End Property
Public Function CreateTextField(ByRef BaseControlId As String, ByRef LabelText As String, Optional ByVal Mandatory As Boolean = False, Optional ByRef ValidationExpression As String = vbNullString) As TextBox
Dim strLabelId As String = String.Concat("lbl", BaseControlId)
Dim strTextBoxId As String = String.Concat("txt", BaseControlId)
Dim div As New HtmlGenericControl("div")
div.Controls.Add(CreateLbl(strLabelId, LabelText, strTextBoxId))
Dim txt As New TextBox
txt.ID = strTextBoxId
txt.Style.Add("border", "solid 1px #8080ff")
div.Controls.Add(txt)
If Mandatory Then
div.Controls.Add(CreateRfv(strTextBoxId))
End If
If ValidationExpression <> vbNullString Then
div.Controls.Add(CreateRev(strTextBoxId, ValidationExpression))
End If
m_ctlPublisher.Controls.Add(div)
Return txt
End Function
Public Function CreateDropDownField(ByRef BaseControlId As String, ByRef LabelText As String) As DropDownList
Dim strLabelId As String = String.Concat("lbl", BaseControlId)
Dim strDropDownId As String = String.Concat("ddl", BaseControlId)
Dim div As New HtmlGenericControl("div")
div.Controls.Add(CreateLbl(strLabelId, LabelText, strDropDownId))
Dim ddl As New DropDownList
ddl.ID = strDropDownId
ddl.Style.Add("border", "solid 1px #8080ff")
div.Controls.Add(ddl)
m_ctlPublisher.Controls.Add(div)
Return ddl
End Function
Public Shared Sub ConfigureForViewing(ParamArray TheViewableControls() As WebControl)
For Each Control As WebControl In TheViewableControls
Control.Style.Value = "border: none; font-weight: bold"
If TypeOf Control Is TextBox Then
DirectCast(Control, TextBox).ReadOnly = True
Else
Control.Enabled = False
End If
Next Control
End Sub
private m_gvw as GridView
public sub BeginCreateGridView(optional byval withSelect as Boolean = False, optional byref dataKeys() as string = nothing)
m_gvw = new GridView()
m_gvw.AutoGenerateColumns = false
m_gvw.HeaderStyle.BackColor = System.Drawing.ColorTranslator.FromHtml("#8080ff")
m_gvw.HeaderStyle.Font.Bold = True
m_gvw.CellPadding = 6
m_gvw.CellSpacing = 0
m_gvw.CssClass = "button"
if withSelect then
dim field as New ButtonField
field.ButtonType = ButtonType.Image
field.ImageUrl = "misc/images/next.gif"
field.CommandName = "Select"
m_gvw.Columns.Add(field)
end if
if not dataKeys is nothing then
m_gvw.DataKeyNames = dataKeys
end if
end sub
public function EndCreateGridView() as GridView
return m_gvw
end function
public sub AddGridViewColumn(byref columnName as String, byref text as String)
Dim field as New BoundField
field.DataField = columnName
field.HeaderText = text
m_gvw.Columns.Add(field)
end sub
Private Function CreateLbl(ByRef Id As String, ByRef Text As String, Optional ByRef ForControlId As String = vbNullString) As Label
Dim lbl As New Label
lbl.ID = Id
lbl.Text = Text
If ForControlId <> vbNullString Then
lbl.AssociatedControlID = ForControlId
End If
lbl.CssClass = m_strLabelCssClass
lbl.Width = m_unitLabelColumnWidth
Return lbl
End Function
Private Function CreateRfv(ByRef ForControlId As String) As RequiredFieldValidator
Dim rfv As New RequiredFieldValidator
rfv.ID = String.Concat("rfv", ForControlId.Substring(3))
rfv.ControlToValidate = ForControlId
rfv.Text = "!"
rfv.Font.Size = FontUnit.Larger
rfv.Font.Bold = True
rfv.Display = ValidatorDisplay.Dynamic
rfv.ValidationGroup = "ValidationGroup1"
Return rfv
End Function
Private Function CreateRev(ByRef ForControlId As String, ByRef ValidationExpression As String) As RegularExpressionValidator
Dim rev As New RegularExpressionValidator
rev.ID = String.Concat("rev", ForControlId.Substring(3))
rev.ControlToValidate = ForControlId
rev.Text = "!"
rev.Font.Size = FontUnit.Larger
rev.Font.Bold = True
rev.Display = ValidatorDisplay.Dynamic
rev.ValidationGroup = "ValidationGroup1"
rev.ValidationExpression = ValidationExpression
Return rev
End Function
End Class
Comments