Set up a Multi-Line Editable GridView Disassociated from a DataSource

Multi-Line Editable Gridview Control
Multi-Line Editable Gridview Control

GridView controls are versatile multi-purpose ASP.NET widgets. I like the default functionality when hooked up to a data source, but depending on a project’s requirements I also like the ability to tweak the default functionality to make the GridView behave in different ways.

For example, in past projects  users have asked me to create a more Excel-like interface for viewing and managing their data. This is certainly possible with a GridView control. To take things one step further, in some cases the GridView can even be used as a UI-specific widget that runs disassociated from a DataSource.

Basically the GridView control can be adjusted to act like a tabular widget on a Web page which allows the user to add/remove/edit multiple rows of information at once. I have not been able to find a front-end only widget of the same calibre that has similar behavior, and coding it completely from scratch using JavaScript and HTML tables seems like overkill.

So How Does One Set Up an Excel-Like GridView Separated from a DataSource?

  1. The first step of the process is to drag a GridView control onto your ASP.NET WebForm in Visual Studio.
  2. A good idea then is to enable theming and then to select a visually appealing theme for your new GridView control using the Auto Format option in the Visual Studio Properties window. In the case of the screen-shot attached to this article I selected the style Mocha.

Now Make your GridView Look Like an Editable SpreadSheet

  1. Once done, it’s time to start editing your default template. To make your GridView look more like an editable spreadsheet you can manually add editable controls to your ASP:TemplateField ItemTemplate columns. The Gridview by default shows ItemTemplate columns so rather than showing read-only labels, we can add editable fields.
  2. Remember also to turn off automatic column generation (AutoGenerateColumns=False) as well as automatic button generation for add/edit/delete buttons (ie: AutoGenerateDeleteButton=False, AutoGenerateEditButton=False, AutoGenerateSelectButton=False). We want to control all of this behavior manually.

Give Users the Ability to Add New Rows to Your GridView

  1. Now add an Add button to one of the table columns of your FooterTemplate. You will want to point this to a custom ASP.NET method where you will back-up your existing GridView structure and then add a new blank row.
  2. Note that to back up your existing GridView structure, you will need to manually handle this due to the Web’s stateless nature. In the code sample below the method called CopyTestGridInfoTable() handles backing up the existing grid into a DataTable by iterating through the Rows of the existing Grid.
  3. As soon as the existing GridView has been backed up into a DataTable, the AddBlankRow() method is called, which simply inserts a blank row of data into the DataTable along with a unique identifier for the new row.
  4. As you can see from the code, the simplest way to get a unique identifier for each row is by using the following: Guid.NewGuid().ToString().GetHashCode().ToString(“x”) . This syntax is used whenever a new or existing row is added to the GridView and is saved to a hidden field within the GridView itself.
  5. Once the new row has been added, the GridView is bound to the updated DataTable and re-rendered on the UI to display to the user.

Give Users the Ability to Remove Rows From Your GridView

  1. Finally, we must also give our users a way to remove any row of the GridView they do not wish to see. This is done by adding a special TemplateField column containing a LinkButton control.
  2. To associate the new Removal LinkButton control with the btnDelete_click deletion method, we set the button’s onCommand option to point to the btnDelete_click deletion method. Then to make sure the correct unique row id is passed to the deletion method, we set the LinkButton’s CommandArgument to be the Uniquely generated Guid that is used when constructing and saving our table.
  3. Then within the btnDelete_click deletion method we call the CopyTestGridInfoTable() method to back up our existing GridView into a DataTable, and then we iterate through the DataRows in the DataTable and delete the row selected by the user using the the Guid unique row identifier.
  4. Finally, we re-bind the GridView to the adjusted DataTable to make sure that the user’s changes show on the UI.

Putting it All Together – The Full Example

Below is a full example page of a multi-line editable GridView control that runs disassociated from a datasource, and that provides the user with the ability to add new rows and delete specific existing rows:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title> 
<script runat="server">
 Protected Sub Page_Load(sender As Object, e As System.EventArgs)
 If Not Page.IsPostBack Then
 SetupTestGridInputFilters()
 End If
 End Sub
 Private Sub SetupTestGridInputFilters()
 Dim dtTestGridInputFilters As New DataTable()
 Dim colOne As New DataColumn("Field", System.Type.GetType("System.String"))
 dtTestGridInputFilters.Columns.Add(colOne)
 Dim colTwo As New DataColumn("Op", System.Type.GetType("System.String"))
 dtTestGridInputFilters.Columns.Add(colTwo)
 Dim colThree As New DataColumn("Val", System.Type.GetType("System.String"))
 dtTestGridInputFilters.Columns.Add(colThree)
 Dim colFour As New DataColumn("RowCount", System.Type.GetType("System.String"))
 colFour.DefaultValue = Guid.NewGuid().ToString().GetHashCode().ToString("x")
 dtTestGridInputFilters.Columns.Add(colFour)
 Session("dtTestGridInputFilters") = dtTestGridInputFilters
 AddBlankRow()
 End Sub
 Protected Sub lbAdd_Click(sender As Object, e As System.EventArgs)
 Session("dtTestGridInputFilters") = CopyTestGridInfoTable()
 AddBlankRow()
 End Sub
 Private Sub AddBlankRow()
 Dim dtTestGridInputFilters As DataTable
 dtTestGridInputFilters = Session("dtTestGridInputFilters")
 Dim blankRow As DataRow = dtTestGridInputFilters.NewRow()
 blankRow("Field") = ""
 blankRow("Op") = ""
 blankRow("Val") = ""
 blankRow("RowCount") = Guid.NewGuid().ToString().GetHashCode().ToString("x")
 dtTestGridInputFilters.Rows.Add(blankRow)
 GridView1.DataSource = dtTestGridInputFilters
 GridView1.DataBind()
 End Sub
 Private Function CopyTestGridInfoTable() As DataTable
 Dim returnValue As DataTable
 returnValue = getWorkingDataTable()
 For Each rowValue As GridViewRow In GridView1.Rows
 Dim drExistingRow = returnValue.NewRow()
 Dim strFieldVal As String = CType(rowValue.FindControl("ddlCustInfoField"), DropDownList).SelectedItem.Value
 Dim strOpVal As String = CType(rowValue.FindControl("ddlCustInfoOp"), DropDownList).SelectedItem.Value
 Dim strSearchVal As String = CType(rowValue.FindControl("txtCustInfoVal"), TextBox).Text
 Dim strRowCntVal As String = CType(rowValue.FindControl("tbRowNum"), TextBox).Text
 drExistingRow.Item("Field") = strFieldVal
 drExistingRow.Item("Op") = strOpVal
 drExistingRow.Item("Val") = strSearchVal
 drExistingRow.Item("RowCount") = strRowCntVal
 returnValue.Rows.Add(drExistingRow)
 Next
 Return returnValue
 End Function
 Private Function getWorkingDataTable() As DataTable
 Dim returnValue As New DataTable()
 Dim dt = TryCast(Session("dtTestGridInputFilters"), DataTable)
 If Not dt Is Nothing Then
 returnValue = dt.Clone()
 End If
 Return returnValue
 End Function
 Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As CommandEventArgs)
 Session("dtTestGridInputFilters") = CopyTestGridInfoTable()
 Dim strRemoveLoc As String = e.CommandArgument
 Dim returnValue As DataTable
 returnValue = Session("dtTestGridInputFilters")
 Dim intRowCnt As Int32 = returnValue.Rows.Count
 If intRowCnt > 1 Then
 For Each checkRow As DataRow In returnValue.Rows
 If (strRemoveLoc).Equals(checkRow("RowCount").ToString) Then
 checkRow.Delete()
 Exit For
 End If
 Next
 Else
 For Each checkRow As DataRow In returnValue.Rows
 checkRow("Field") = ""
 checkRow("Op") = ""
 checkRow("Val") = ""
 Next
 End If
 GridView1.DataSource = returnValue
 GridView1.DataBind()
 End Sub
</script>
</head>
<body>
 <form id="form1" runat="server">
 <div>

 <Table ID="Table1" Width="1303px">
 <tr><td colspan="2">
 <!-- PLACE HEADER HERE -->
 </td></tr>
 <tr><td>
 <!-- BODY LAYOUT ROW 1 Column 1-->
 <asp:Label ID="Label1" runat="server" Text="TestGrid Information"></asp:Label><br />
 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
 BackColor="White" BorderColor="#DEDFDE" 
 BorderStyle="None" BorderWidth="1px" CellPadding="4" ForeColor="Black" 
 GridLines="Vertical" ShowFooter="True" >
 <AlternatingRowStyle BackColor="White" />
 <Columns>
 <asp:TemplateField>
 <ItemTemplate>
 <asp:LinkButton ID="lbDelete" runat="server" OnCommand="btnDelete_Click" CommandName="Delete" CommandArgument='<%#Eval("RowCount") %>'>Remove</asp:LinkButton>
 <asp:TextBox ID="tbRowNum" runat="server" style="display:none;" text='<%#Bind("RowCount") %>'></asp:TextBox>
 </ItemTemplate>
 <FooterTemplate>
 </FooterTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="Field">
 <ItemTemplate>
 <asp:DropDownList id="ddlCustInfoField" runat="server" SelectedValue='<%#Bind("Field") %>'>
 <asp:ListItem Value=""></asp:ListItem>
 <asp:ListItem Value="test">test</asp:ListItem>
 </asp:DropDownList>
 </ItemTemplate>
 <FooterTemplate>
 </FooterTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="Op">
 <ItemTemplate>
 <asp:DropDownList id="ddlCustInfoOp" runat="server" SelectedValue='<%#Bind("Op") %>'>
 <asp:ListItem Value=""></asp:ListItem>
 <asp:ListItem Value="=">=</asp:ListItem>
 <asp:ListItem Value="*">*</asp:ListItem>
 <asp:ListItem Value="a string">a string</asp:ListItem>
 <asp:ListItem Value="test data">test data</asp:ListItem>
 </asp:DropDownList>
 </ItemTemplate>
 <FooterTemplate></FooterTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="Value">
 <ItemTemplate>
 <asp:TextBox id="txtCustInfoVal" runat="server" Text='<%# Bind("Val") %>'>
 </asp:TextBox>
 </ItemTemplate>
 <FooterTemplate>
 <asp:LinkButton ID="lbAdd" runat="server" OnClick="lbAdd_Click">Add a Row</asp:LinkButton></FooterTemplate>
 </asp:TemplateField>
 </Columns>
 <EmptyDataTemplate>
 No results
 </EmptyDataTemplate>
 <FooterStyle BackColor="#CCCC99" />
 <HeaderStyle BackColor="#6B696B" Font-Bold="True" ForeColor="White" />
 <PagerStyle BackColor="#F7F7DE" ForeColor="Black" HorizontalAlign="Right" />
 <RowStyle BackColor="#F7F7DE" />
 <SelectedRowStyle BackColor="#CE5D5A" Font-Bold="True" ForeColor="White" />
 <SortedAscendingCellStyle BackColor="#FBFBF2" />
 <SortedAscendingHeaderStyle BackColor="#848384" />
 <SortedDescendingCellStyle BackColor="#EAEAD3" />
 <SortedDescendingHeaderStyle BackColor="#575357" />
 </asp:GridView>
 </td><td>
 </td></tr>
 </Table></div>
 </form>
</body>
</html>

 

Advertisements

5 thoughts on “Set up a Multi-Line Editable GridView Disassociated from a DataSource

    1. Hi Vishal, glad you liked the post!

      As you say, there are lots of great tools like farpoint grid out there that give full Excel-like functionality on the Web. These are definitely worth picking up if one needs spreadsheet capabilities online.

      In this article I am giving the example of the adjusted GridView to show its flexibility as a basic control. I am hoping this will be useful to people looking to see what the GridView can do, or even if they want the GridView to appear as act as a multi-row editing widget rather than its default behavior of line-by-line editing.

      Again, thanks for your comment, and glad you found the post interesting!

  1. Hi this is laxman could u help me please
    i want display in the gridview in the first row as textbox and second row as dropdownlist and third row radio button this is my Question

    please give me ans’s from any one

    thanks
    laxman pantham

    1. Hi, for the most layout flexibility you could try using a ListView rather than a GridView. Alternately, you could change your GridView column to a TemplateField and then enter the HTML for a three row table containing the TextBox/DropDownList/RadioButton controls as you mentioned.

      Hope this helps

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s