Part 1: GridView VS dynamic HTML Table (ASP.NET WebForms)

Replacing GridView with dynamic HTML Table in ASP.NET WebForms.

A comparison of approaches of doing a table in ASP.NET WebForms.

Resource:

Introduction

In this article, we’ll going to do a comparison of 2 methods for doing a table in ASP.NET WebForms. Namely:

  1. GridView and
  2. dynamic HTML table.

The purpose of this article is to present an alternative way to do a table as to the traditional way of GridView.

This article serves as a side by side comparison as for how the dynamic HTML table can be achieved for replacing GridView in action.

The Coding

First of all, let’s use a simple class object as a container to hold data.

class Member
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateRegister { get; set; }
    public int Gender { get; set; }

    public Member(int id, string name, DateTime dateRegister, int gender)
    {
        Id = id;
        Name = name;
        DateRegister = dateRegister;
        Gender = gender;
    }

    public string GenderStr
    {
        get
        {
            switch (Gender)
            {
                case 1:
                    return "Male";
                case 2:
                    return "Female";
                default:
                    return "Other";
            }
        }
    }

    public string DateRegisterStr
    {
        get
        {
            if (DateRegister == DateTime.MinValue)
                return "---";
            return DateRegister.ToString("dd MMM yyyy");
        }
    }

    public string DateRegisterData
    {
        get
        {
            if (DateRegister == DateTime.MinValue)
                return "";
            return DateRegister.ToString("yyyy-MM-dd");
        }
    }

    public string SelectGender(int g)
    {
        if (g == Gender)
            return "selected";
        return "";
    }
}

Some helper methods:

public class helper
{
    public static List<Member> GetMemberList()
    {
        List<Member> lst = new List<Member>();

        lst.Add(new Member(1, "James", new DateTime(2022, 11, 11), 1));
        lst.Add(new Member(2, "Amy", new DateTime(2022, 11, 10), 2));
        lst.Add(new Member(3, "Smith", new DateTime(2022, 10, 8), 1));
        lst.Add(new Member(4, "Cait", new DateTime(2022, 9, 7), 2));

        return lst;
    }

    public static DateTime ConvertToDate(string input)
    {
        DateTime date = DateTime.MinValue;

        try
        {
            if (!string.IsNullOrWhiteSpace(input))
            {
                string[] da = input.Split('-');
                int year = Convert.ToInt32(da[0]);
                int month = Convert.ToInt32(da[1]);
                int day = Convert.ToInt32(da[2]);

                date = new DateTime(year, month, day);
            }
        }
        catch { }

        return date;
    }
}

Round 1: Build a Simple Table

Let’s build a simple table as below:

The GridView Method:

The front page:

Note: Always switch off ViewState if not using the “state” function, by applying the property of  EnableViewState="False".

<asp:GridView ID="gv1" runat="server" AutoGenerateColumns="false" EnableViewState="false">
    <Columns>
        <asp:BoundField HeaderText="ID" DataField="Id" />
        <asp:HyperLinkField HeaderText="Name" DataTextField="Name"
         DataNavigateUrlFields="Id" DataNavigateUrlFormatString="ViewMember.aspx?id={0}" />
        <asp:BoundField HeaderText="Gender" DataField="GenderStr" />
        <asp:BoundField HeaderText="Date Register" DataField="DateRegisterStr" />
    </Columns>
</asp:GridView>

The code behind:

var lst = helper.GetMemberList();
gv1.DataSource = lst;
gv1.DataBind();

The dynamic HTML Method:

The front page:

Apply some basic styling at the header:

<styletype="text/css">.tb1table{border-collapse:collapse;}.tb1th{border:1pxsolidblack;}.tb1td{border:1pxsolidblack;}</style>

Then,body components:

<divclass="tb1"><asp:PlaceHolderID="ph1"runat="server"></asp:PlaceHolder></div>

The code behind:

varlst=helper.GetMemberList();StringBuildersb=newStringBuilder();sb.Append(@"<table><tr><th>ID</th><th>Name</th><th>Gender</th><th>Date Register</th></tr>");foreach(varminlst){    sb.Append($@"<tr><td>{m.Id}</td><td><a href='ViewMember.aspx?id={m.Id}'>{m.Name}</a></td><td>{m.GenderStr}</td><td>{m.DateRegisterStr}</td></tr>");}sb.Append("</table>");ph1.Controls.Add(newLiteralControl(sb.ToString()));

Round 2:Apply Theme or Styling

Let’s take this design as example:

The GridView Method:

You can either use the limited pre-designed default colors (the quick way),like this:

Image 4

Or manually code it at the front page like:

<asp:GridViewID="gv2"runat="server"AutoGenerateColumns="False"  EnableViewState="False"CellPadding="10"ForeColor="#333333"GridLines="None"><AlternatingRowStyleBackColor="White"/><Columns><asp:BoundFieldHeaderText="ID"DataField="Id"/><asp:HyperLinkFieldHeaderText="Name"DataTextField="Name"DataNavigateUrlFields="Id"DataNavigateUrlFormatString="ViewMember.aspx?id={0}"/><asp:BoundFieldHeaderText="Gender"DataField="GenderStr"/><asp:BoundFieldHeaderText="Date Register"DataField="DateRegisterStr"/></Columns><EditRowStyleBackColor="#7C6F57"/><FooterStyleBackColor="#1C5E55"Font-Bold="True"ForeColor="White"/><HeaderStyleBackColor="#1C5E55"Font-Bold="True"ForeColor="White"/><PagerStyleBackColor="#666666"ForeColor="White"HorizontalAlign="Center"/><RowStyleBackColor="#E3EAEB"/><SelectedRowStyleBackColor="#C5BBAF"Font-Bold="True"ForeColor="#333333"/><SortedAscendingCellStyleBackColor="#F8FAFA"/><SortedAscendingHeaderStyleBackColor="#246B61"/><SortedDescendingCellStyleBackColor="#D4DFE1"/><SortedDescendingHeaderStyleBackColor="#15524A"/></asp:GridView>

Or you can also apply the class directly by applying 2 properties to the GridView component:

CssClass="table1"GridLines="None"

Example:

<asp:GridViewID="gv2"runat="server"CssClass="table1"GridLines="None"  AutoGenerateColumns="False"EnableViewState="False"><Columns><asp:BoundFieldHeaderText="ID"DataField="Id"/><asp:HyperLinkFieldHeaderText="Name"DataTextField="Name"  DataNavigateUrlFields="Id"DataNavigateUrlFormatString="ViewMember.aspx?id={0}"/><asp:BoundFieldHeaderText="Gender"DataField="GenderStr"/><asp:BoundFieldHeaderText="Date Register"DataField="DateRegisterStr"/></Columns></asp:GridView>

The dynamic HTML Method:

Note:Using CSS to style table is the most “nature”and “native”way in the universe of web development. Hence,this is strongly recommended to code this way rather than the GridView styling.

Use CSS Styling block:

<styletype="text/css">.tb1table{border-collapse:collapse;}.tb1th{border:1pxsolidblack;background:#1C5E55;color:white;padding:10px;border:none;}.tb1td{border:1pxsolidblack;color:#333333;padding:10px;border:none;}.tb1tr:nth-child(even){background:#E3EAEB;}</style>

and the body component… same:

<divclass="tb1"><asp:PlaceHolderID="ph1"runat="server"></asp:PlaceHolder></div>

Round 3:Building a Form Table

Let’s take this form table as example:

The GridView Method:

Note 1: for this to work,you must enable the ViewState for GridView component.

For example:

<asp:GridViewID="gv3"runat="server"EnableViewState="True"></asp:GridView>

or simply

<asp:GridViewID="gv3"runat="server"></asp:GridView>

as ViewState is normally turned on by default.

Note 2:ViewState helps to maintain the “state”or the data before and after postback. But there’s a drawback,ViewState will increase the page size that’s being transmitted to end-user’s web browser. The larger the GridView,the larger of page size will be. For more information on ViewState,please do further research on the topic “How ASP.NET ViewState works”? and also research for “Compressing ViewState”.

The front page coding:

<asp:GridViewID="gv3"runat="server"AutoGenerateColumns="False" CellPadding="10"ForeColor="#333333"GridLines="None">    <AlternatingRowStyleBackColor="White"/>    <Columns>        <asp:BoundFieldHeaderText="ID"DataField="Id"/>        <asp:TemplateFieldHeaderText="Name">            <ItemTemplate>                <asp:TextBoxID="txtName"runat="server"></asp:TextBox>            </ItemTemplate>        </asp:TemplateField>        <asp:TemplateFieldHeaderText="Gender">            <ItemTemplate>                <asp:DropDownListID="dropGender"runat="server">                    <asp:ListItemValue="1"Text="Male"></asp:ListItem>                    <asp:ListItemValue="2"Text="Female"></asp:ListItem>                    <asp:ListItemValue="0"Text="Other"></asp:ListItem>                </asp:DropDownList>            </ItemTemplate>        </asp:TemplateField>        <asp:TemplateFieldHeaderText="Date Register">            <ItemTemplate>                <asp:TextBoxID="txtDateRegister"runat="server"TextMode="Date">  </asp:TextBox>            </ItemTemplate>        </asp:TemplateField>        <asp:TemplateFieldHeaderText="Remove">            <ItemTemplate>                <asp:CheckBoxID="cbRemove"runat="server"/>            </ItemTemplate>        </asp:TemplateField>    </Columns>    <EditRowStyleBackColor="#7C6F57"/>    <FooterStyleBackColor="#1C5E55"Font-Bold="True"ForeColor="White"/>    <HeaderStyleBackColor="#1C5E55"Font-Bold="True"ForeColor="White"/>    <PagerStyleBackColor="#666666"ForeColor="White"HorizontalAlign="Center"/>    <RowStyleBackColor="#E3EAEB"/>    <SelectedRowStyleBackColor="#C5BBAF"Font-Bold="True"ForeColor="#333333"/>    <SortedAscendingCellStyleBackColor="#F8FAFA"/>    <SortedAscendingHeaderStyleBackColor="#246B61"/>    <SortedDescendingCellStyleBackColor="#D4DFE1"/>    <SortedDescendingHeaderStyleBackColor="#15524A"/></asp:GridView>

The code behind for loading the GridView:

gv3.DataSource=lst;gv3.DataBind();for(inti=0;i<lst.Count;i++){    GridViewRowgr=gv3.Rows[i];    vartxtName=(TextBox)gr.FindControl("txtName");    vardropGender=(DropDownList)gr.FindControl("dropGender");    vartxtDateRegister=(TextBox)gr.FindControl("txtDateRegister");    varm=lst[i];    txtName.Text=m.Name;    dropGender.SelectedValue=m.Gender.ToString();    txtDateRegister.Text=m.DateRegisterData;}

The code behind for saving the GridView form:

// declare a list to store dataList<Member>lst=newList<Member>();for(inti=0;i<gv3.Rows.Count;i++){    GridViewRowgr=gv3.Rows[i];    varcbRemove=(CheckBox)gr.FindControl("cbRemove");    if(cbRemove.Checked)   {        // remove        continue;   }    intid=Convert.ToInt32(gr.Cells[0].Text);    vartxtName=(TextBox)gr.FindControl("txtName");    vardropGender=(DropDownList)gr.FindControl("dropGender");    vartxtDateRegister=(TextBox)gr.FindControl("txtDateRegister");    vardate=helper.ConvertToDate(txtDateRegister.Text);    intgender=Convert.ToInt32(dropGender.SelectedValue);    lst.Add(newMember(id,txtName.Text,date,gender));}

The dynamic HTML Method:

The front page body component… same:

<divclass="tb1"><asp:PlaceHolderID="ph1"runat="server"></asp:PlaceHolder></div>

The code behind for loading the HTML table:

StringBuildersb=newStringBuilder();sb.Append(@"<table><tr><th>ID</th><th>Name</th><th>Gender</th><th>Date Register</th><th>Remove</th></tr>");foreach(varminlst){    stringname=Server.HtmlEncode(m.Name);    sb.Append($@"<tr><td>{m.Id}</td><td><input name='input_{m.Id}_name'type='text'value='{name}'/></td><td><select name='input_{m.Id}_gender'><option value='1'{m.SelectGender(1)}>Male</option><option value='2'{m.SelectGender(2)}>Female</option><option value='0'{m.SelectGender(0)}>Other</option></select><td><input name='input_{m.Id}_date'type='date'value='{m.DateRegisterData}'/></td><td><input name='input_{m.Id}_remove'type='checkbox'/></td></tr>");}sb.Append("</table>");ph1.Controls.Add(newLiteralControl(sb.ToString()));

The code behind for saving the HTML table form:

// declare a dictionary to store the dataDictionary<int,Member>dicMember=newDictionary<int,Member>();foreach(varkeyinRequest.Form.AllKeys){    if(key.StartsWith("input_"))   {        string[] ka=key.Split('_');        intid=Convert.ToInt32(ka[1]);        if(dicMember.ContainsKey(id))            continue;        if(Request[$"input_{id}_remove"] !=null)       {            // remove            dicMember[id]=newMember(id,0);       }        else       {            stringname=Request[$"input_{id}_name"];            intgender=Convert.ToInt32(Request[$"input_{id}_gender"]);            stringdateinput=Request[$"input_{id}_date"];            DateTimedate=helper.ConvertToDate(dateinput);            dicMember[id]=newMember(id,name,date,gender);       }   }}List<Member>lst=newList<Member>();foreach(varkvindicMember){    if(kv.Value.Status==1)        lst.Add(kv.Value);}

The Javascript Method:

Ideally,to handle dynamic table form,another better way is to use javascript (AJAX) and handle it at the client side. This will be part 2. Continue part 2 at:

https://adriancs.com/c-sharp/404/part-2-gridview-vs-dynamic-html-table-asp-net-webforms/

Pros of Using dynamic HTML Table

  • Very flexible in terms of manipulating the table’s structure
  • Handle dynamic columns as ease (where the total if columns is unpredictable)
  • Very easy to handle header colspan
  • Very easy to apply different styling strategy (by using CSS)
  • Code is cleaner.
  • More nature and native to web development.
  • Multi data field can be easily be arranged and displayed in table cell,including image components.