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

Popular posts from this blog

Auto Mapper and Record Types - will they blend?

Unit testing your Azure functions - part 2: Queues and Blobs

Testing WCF services with user credentials and binary endpoints