Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Simply Expanding ASP.NET GridView

3.43/5 (5 votes)
17 Mar 2008CPOL1 min read 1   282  
ASP.NET GridView which only displays as many rows as the user is willing to fill on the client-side. Uses ASP.NET, C#, JavaScript, Regular Expressions, CSS, and HTML.

Introduction

This is a simple solution to a simple problem. It shows an ASP GridView which when rendered in HTML expands row by row when needed. In other words, it's GridView expand on-demand.

Background

A coworker asked about having a GridView which would have rows dynamically show as long as the user keeps entering or editing data. There were ideas about using AJAX for it or other new fancy technologies. However, since on each new line adding, no new server data is required, I thought that this problem could be solved with lesser effort.

How the code works

*Since it's done in VS 2008, some syntax may be different.

The idea is that we bring the whole table (with full or empty rows) where the last updatable (meaning that the user can change its value) control in each row invokes a JavaScript function which will "add" another row:

JavaScript
function ShowNextLine(what)
{
    //below I use a simple regular expression which 
    //searches for a number. Often you may have your controls
    //which have numbers in their names - this will make 
    //the reg exp find that number, but not the "row" number 
    //therefore you will either need to rename your controls 
    //(GridView or Foo instead of GridView1)
    //or come up with a more flexible regular expression. 
    //I'd prefer the former for it's more comprehensive plus 
    //reg exps eat CPU. 

    //Get the number part of the  item (what) ID
    var s = parseInt(what.id.substring(what.id.search("\\d")));
    //take the "text part" of tr's id and concat 
    //it with an incremented what's - current Id
    document.getElementById("GridView_" + 
      (parseInt(s)+1).toString()).setAttribute("class","trVisible"); 
}

As you can see from the code, it doesn't add the next line, but makes it visible, through changing its CssClass. Prior to that, however, you have to make it invisible.

Rows are rendered in HTML as <TR>. In order to make a <TR> invisible, we can't use "visibility:hidden", nor can we use "height:0px". None of these would do the job. Only "display:none" will:

CSS
<style type="text/css">
    .trInvisible
    {        
        display:none;
    }
    .trVisible
    {
      display:table-row;
    }
</style>

When each table row is bound, we format it appropriately and set its CssClass value to "trInvisible". Read comments in the code:

C#
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
//this will fire on each row of the datasource 
{
    // (our datatable in this case) being bound to the GridView. 
    e.Row.ID = (this.j).ToString();
    //here we are setting the row id (rendered as <TR>
    //in HTML) to the counter - a secuential number;
    
    TextBox txtLastControlInRow = 
       (TextBox)e.Row.FindControl("txtDescription");
       // get the reference to the last textbox in the row
    if (txtLastControlInRow != null) //if it ain't null
    { 
        txtLastControlInRow.Attributes.Add("onfocus", 
          "ShowNextLine(this)");
          //add a JavaScript function call on control focus.
    }
        
    if (this.j > 1) //if this is not the header or the first row
    {
        e.Row.CssClass = "trInvisible";
        //make the row invisible through 
        //specifying the appropriate CSS class
    }
    this.j = this.j + 1; //increment the class global counter.
}

Before the table could be bound, we create a sample one:

C#
private DataTable CreateFooTable()
//this will create a table, which we use to display the grid
{
    //this table is only for demonstration purposes
    //I could have used any other source of data (XML, Database, CSV, whatever)
    //But I chose making the table on the spot
    
    DataTable dt = new DataTable(); //the table to be created;
    int i = 1;

    dt.Columns.Add("Item_Id"); //add ID column
    dt.Columns.Add("Item_Description"); //add whatever other column(s);

    for (i=1; i <= 20; i++) //add 20 rows; 
    {
        dt.Rows.Add(i, "Foo Item " + i.ToString());
        //I am simply adding rows with i in first 
        //column and Item_i into the second;
    }

    return dt; //when the table is 20 rows, return it;
}

Points of interest

  1. It's a nice little exercise for using a combination of various technologies.
  2. Only "display:none" will make a table row invisible.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)