Introduction
This article describes how to use data-grid as an data entry object rather than just considering it as an reporting tool.
Background
In ASP.Net we frequently create dynamic controls (rows) using ASP.Net Web Control table. The major reason behind it is the ease of creation. Most of the times the developers prefer the �System.Web.UI.WebControls.Table� over datagrid because it is analogous to the HTML table. In our project we opted for another approach, we tried to use data-grid. After implementing the solution using Datagrid we felt it is not only simpler to implement but also alignment and most of the UI features are automatically handled.
In our project we had to generate the rows on click of �Add� button and had to delete that particular row on click of �Delete� row button.
Using the code
1. Creating the skeleton of the controls needed in datagrid
We first need to create the structure/skeleton for the controls. On click of �Add� button the controls would be created and displayed in the datagrid. You can create the framework in the design view itself; however experienced programmers would prefer creating it in the �HTML� view.
You can add �ASP Validators� within the �� incase you wish to perform any validations over the data entered by the user.
<asp:datagrid id="dgARecord" runat="server" Width="100%" CellPadding="2"
AutoGenerateColumns="False"
OnItemDataBound="dgARecord_ItemDataBound"
OnDeleteCommand="dgARecord_Delete">
<ItemStyle CssClass="txthLabel"></ItemStyle>
<HeaderStyle Font-Bold="True" CssClass="btnActionh"></HeaderStyle>
<FooterStyle CssClass="btnActionh"></FooterStyle>
<Columns>
<asp:TemplateColumn HeaderText="S.No" ItemStyle-HorizontalAlign="Center"
ItemStyle-Width="15%">
<ItemStyle CssClass="ContentSpacer" Width="10%"></ItemStyle>
<ItemTemplate>
<asp:label text='<%# DataBinder.Eval(Container.DataItem,
"SerialNumberA")%>' id="SerialNumberA" runat="server" EnableViewState="true"
CssClass="txthLabel">
</asp:label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="HostName Value"
ItemStyle-HorizontalAlign="Center" ItemStyle-Width="25%">
<ItemStyle CssClass="ContentSpacer"></ItemStyle>
<ItemTemplate>
<asp:TextBox id="txtHostNameValueA" runat="server" CssClass="txthLabel"
MaxLength="50"></asp:TextBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="IPAddress Value"
ItemStyle-HorizontalAlign="Center" ItemStyle-Width="25%">
<ItemStyle CssClass="ContentSpacer"></ItemStyle>
<ItemTemplate>
<asp:TextBox id="txtIPValueA" runat="server"
CssClass="txthLabel"></asp:TextBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:ButtonColumn Text="Delete" ButtonType="PushButton" HeaderText="Delete
Row" CommandName="Delete"
ItemStyle-HorizontalAlign="Center" ItemStyle-Width="15%">
<ItemStyle CssClass="ContentSpacer"></ItemStyle>
</asp:ButtonColumn>
</Columns>
</asp:datagrid>
<asp:RequiredFieldValidator
id="lblErrorHost" Runat="server" ErrorMessage="Host Name is required."
ControlToValidate="txtHostNameValue">*</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator
ControlToValidate="txtHostNameValue" Runat="server" ErrorMessage='Your Hostname
Value must be a Fully Qualified Domain name e.g. test999.ab.ad.op.com'
ValidationExpression="\w+([-]\w+)*\.\w+([-]\w+)*\.\w+([-.]\w+)*"
ID="regHNC">*</asp:RegularExpressionValidator>
2. Binding the dataset to the datagrid
We need to display the data inputted by the user or the data from the database. We had the data inserted by the User, we can save the data inputted by the user in �Session�, �ViewState�, �Application� object or else can create a temporary table in the database and display it accordingly, this technique can be applied if the network speed is not an issue and also the numbers of users accessing the application are few.
Usually it is better to go for �Hidden� or �ViewState� objects. In our application we needed to preserve the data inputted by the user in the �Add Request� and �Delete Request� pages hence we opted for �Session� variables.
In Step 1 we create add those many rows created/added by the user. ShowGridARecord()method takes care of the same.
Public Sub ShowGridARecord()
Dim dtTemp As DataTable = New DataTable
Dim intCounter As Integer
Dim intRowCountARecord As Integer
Dim drCol As DataColumn
drCol = New DataColumn("SerialNumberA")
dtTemp.Columns.Add(drCol)
If (ViewState("rowCntA") Is Nothing) Then
intRowCountARecord = 0
Else
intRowCountARecord = ViewState("rowCntA")
End If
For intCounter = 0 To intRowCountARecord
Dim drRow As DataRow
drRow = dtTemp.NewRow()
drRow.Item(0) = intCounter + 1
dtTemp.Rows.Add(drRow)
drRow = dtTemp.NewRow()
Next
dgARecord.DataSource = dtTemp.DefaultView
dgARecord.DataBind()
End Sub
In Step 1 we insert the data in the respective columns � the data which has been inputted by the user. The last line of the ShowGridARecord() method asks for the databind of the datagrid. This passes the control to the �ItemDataBound� method.
This is the place where we write the code which insert the values in the appropriate controls of the datagrid.
Public Sub dgARecord_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgARecord.ItemDataBound
HNValA = Session("HostNameArrayA")
IPValA = Session("IPArrayA")
If (e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.EditItem) Then
Dim txtHostNameValueA As TextBox = DirectCast(e.Item.FindControl("txtHostNameValueA"), TextBox)
txtHostNameValueA.Text = HNValA(e.Item.ItemIndex)
Dim txtIPValueA As TextBox = DirectCast(e.Item.FindControl("txtIPValueA"), TextBox)
txtIPValueA.Text = IPValA(e.Item.ItemIndex)
End If
End Sub
3. Applying CSS class to the controls on the fly
As we had already mentioned that applying formatting and styles over datagrid is very simple, as most of the things are done by ASP.Net itself. You can see how easily we have applied style-class on newly created controls.
Private Sub dgARecord_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgARecord.ItemCreated
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim myButton As Button = DirectCast(e.Item.Cells(3).Controls(0), Button)
myButton.CssClass = "btnAction"
End If
End Sub
4. Adding rows to the datagrid
On click of �Add� button we firstly save the data entered by the user in the �ViewState� or �Session� variable after that we increment the counter of number of rows. The next step includes generating the rows/controls of the datagrid depending on the number of the counter and then inserting the values (last entered) by the user in the counter.
Private Sub btnAddA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddA.Click
If (ViewState("rowCntA") < 9) Then
Dim intCounter As New Integer
Dim leave As New Integer
Dim intRowCountARecord As Integer
leave = 0
If (ViewState("rowCntA") Is Nothing) Then
intRowCountARecord = 0
Else
intRowCountARecord = CType(ViewState("rowCntA"), Integer)
End If
For intCounter = 0 To intRowCountARecord
Dim txtHNGet As TextBox
txtHNGet = dgARecord.Items(intCounter).Cells(1).Controls(1)
If txtHNGet.Text = "" Then
HNValA(intCounter) = txtHNGet.Text.Trim
leave = 1
End If
HNValA(intCounter) = txtHNGet.Text
Dim txtIPGet As TextBox
txtIPGet = dgARecord.Items(intCounter).Cells(2).Controls(1)
If txtIPGet.Text = "" Then
IPValA(intCounter) = txtIPGet.Text.Trim
leave = 1
End If
IPValA(intCounter) = txtIPGet.Text.Trim
Next
If (leave = 1) Then
Exit Sub
End If
Session("HostNameArrayA") = HNValA
Session("IPArrayA") = IPValA
ViewState("rowCntA") += 1
ShowGridARecord()
Else
lblErrorMessage.Text = "You cannot add more than 10 Request." & C_VERTICAL_SPACER
End If
End Sub
5. Deleting rows from the datagrid
On click of �Delete� button we firstly save the data entered by the user in the �ViewState� or �Session� variable, in this step we save the data of all the rows apart from the row for which user has clicked the delete button �UpdateEntriesARecord(e.Item.ItemIndex)� takes care of the same.After that we decrement the counter of number of rows. The next step includes generating the rows/controls of the datagrid depending on the number of the counter and then inserting the values (last entered) by the user in the counter.
Sub dgARecord_Delete(ByVal sender As Object, ByVal e As DataGridCommandEventArgs)
If (ViewState("rowCntA") < 1) Then
lblErrorMessage.Text = "You have to process atleast one request." & C_VERTICAL_SPACER
lblErrorMessage.Visible = True
Else
UpdateEntriesARecord(e.Item.ItemIndex)
dgCNameRecord.EditItemIndex = -1
ShowGridARecord()
End If
End Sub
Private Sub UpdateEntriesARecord(ByVal index As Integer)
Dim intCounter As New Integer
Dim intRecordCounterARecord As Integer
Dim intArrayCounter As Integer
intArrayCounter = 0
If (ViewState("rowCntA") Is Nothing) Then
intRecordCounterARecord = 0
Else
intRecordCounterARecord = CType(ViewState("rowCntA"), Integer)
End If
For intCounter = 0 To intRecordCounterARecord
If (intCounter <> index) Then
Dim txtHNGet As TextBox
txtHNGet = dgARecord.Items(intCounter).Cells(1).Controls(1)
HNValA(intArrayCounter) = txtHNGet.Text.Trim
Dim txtIPGet As TextBox
txtIPGet = dgARecord.Items(intCounter).Cells(2).Controls(1)
IPValA(intArrayCounter) = txtIPGet.Text.Trim
intArrayCounter += 1
End If
Next
Session("HostNameArrayA") = HNValA
Session("IPArrayA") = IPValA
ViewState("rowCntA") -= 1
End Sub
Advantages
1) Less time required for formatting and applying styles over the newly created controls
2) Simple to implement
Disadvantages
1) Performance is mainly a concern when datagrid is used. However we can improve the performance if we disable the �EnableViewState� property at the page level
Conclusion
1) Please note that using ASP.Net Tables also we can achieve the similar functionality. The purpose of the BOK is just to show that we can implement the dynamic control features using Datagrid and that too in less time.