EmptyDataTemplate in GridView Or Data Controls in ASP.NET 3.5 or 4.0

How to display a table when no records are present in the Database? This is the most frequently asked question for beginners, even for intermediate developers, while displaying data on the web forms when there are no records present in the Database. Most of us, to satisfy our requirements, switch the EmptyDataText property setting of the GridView control or any DataControl by specifying the value as "No Records Found". But there are sometimes a requirement to display a table on the web page if there is no records found in the database so that the user can add a new record by filling in the fields on the table and by clicking the button. In such cases we mostly make use of a table control along with the GridView control whereby setting its (the table's) visibility to true or false depending on whether there are records in the DB or not. The alternative is to use an EmptyDataTemplate of the GridView control or the data control, whichever you are using. Whereby the user must input the data in the respective fields and on the click of the button, all the data entered by the user is stored in the DB and finally the stored Data is displayed in the GridView control. Something about the EmptyDataTemplate is that it's a template that can display any piece of information in a specified format when no records are present in the Database. You need to explicitly define the EmptyDataTemplate for your Data Control. It's simple to define the only thing that you need to do, which is to create a class that will implement the ITemplate interface and define your layout of your EmptyDataTemplate. And then finally you need to set the GridView.EmptyDataTemplate to your Template (that you created).

Ok now let's move on towards our example, as you all know. Now let's try to implement our goal.

1. Starting with our That Queries. Over here we'll be making use of an Employees table stored in an Oracle Database. The following is the script for that:

  1. create table Employees  
  2. (  
  3. EId int not null,  
  4. EName varchar(30),  
  5. EAddress varchar(30),  
  6. EAge Number,  
  7. ECountry varchar(30),  
  8. EDesignation varchar(30)  
  9. )  
  10. //For Accessing the Data stored in Employees Table  
  11. create or replace procedure prcGetEmployees  
  12. (  
  13. temp_cursor out sys_refCursor  
  14. )  
  15. as  
  16. begin  
  17. open  temp_cursor for  
  18. select * from Employees;  
  19. end;  
  20. //For Inserting the Data in Employees Table  
  21. create or replace procedure prcAddEmp  
  22. (  
  23. v_name varchar2,  
  24. v_address varchar2,  
  25. n_age number,  
  26. v_country varchar2,  
  27. v_designation varchar2  
  28. )  
  29. as  
  30. v_id number:=0;  
  31. begin  
  32. select count(*) into v_id from Employees;  
  33. v_id:=v_id+1;  
  34. insert into Employees  
  35. values (v_id,v_name,v_address,n_age,v_country,v_designation);  
  36. end; 

Until now we have created a table and a procedure that will allow us to read the Employees table information or insert data into the Employees table. Now let's use a webform in Visual Studio 2010 (named test.aspx in our project) and add a gridview to the test.aspx page and on the page load event call the procedure that provides us Employee data, in our case prcGetEmployees is the procedure that, when executed, will return the resultset of the Employees table.

Test.aspx

EmptyDataTemp1.jpg

Test.aspx.cs Code Behind

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Data;  
  8. public partial class test : System.Web.UI.Page  
  9. {  
  10.     protected void Page_Load(object sender, EventArgs e)  
  11.     {  
  12.         if (!IsPostBack)  
  13.             LoadData();  
  14.     }  
  15.     private void LoadData()  
  16.     {  
  17.         DAL objDal = new DAL();  
  18.         DataSet ds = objDal.GetRecords();  
  19.         if (ds != null)  
  20.         {  
  21.             GridView1.DataSource = ds.Tables[0].DefaultView;  
  22.             GridView1.DataBind();  
  23.         }  
  24.     }  
  25. } 

Now when I try to run the file all I get is a blank page like the following.

EmptyDataTemp2.jpg

This is because I neither set the EmptyDataTextProperty to "No Records Found" nor did I use an EmptyDataTemplate.

Ok, now let's move toward creating an EmptyDataTemplate for our Employee Table. For creating a table we need the cell, in other words the Column and the Row. The following are the two classes that we can call; they have helper classes that will allow us to create a column and a row for our GridView's EmptyDataTemplate.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI.WebControls;  
  6. using System.ComponentModel;  
  7. using System.Reflection;  
  8. using System.Collections;  
  9. using System.Web.UI;  
  10. /// <summary>  
  11. /// This class will act a as column of EmptyDataTemplate Table.  
  12. ///This class is used by EmptyGridRow class  
  13. /// </summary>  
  14. public class EmptyColumn  
  15. {  
  16.     //specifies the column text to be displayed  
  17.     public string ColumnName { getset; }  
  18.     //specifies whether the column is ready only or not  
  19.     public bool IsReadOnly { getset; }  
  20.     //the control to use for the column  
  21.     public WebControl ColumnControl { getset; }  
  22.     //setting the default control as Label.  
  23.     public EmptyColumn()  
  24.     {  
  25.         ColumnControl = new Label();  
  26.     }  
  27. }  
  28. /// <summary>  
  29. /// This class act as a row of EmptyDataTemplate Table.  
  30. ///This class is used by EmptyGridTemplate.  
  31. /// </summary>  
  32. public class EmptyGridRow  
  33. {  
  34.     //Specifies EmptyColumn Properties  
  35.     public EmptyColumn Columns { getset; }  
  36.     //the default cell size within a row. i.e. Maximum 2 cells will be there inside a row  
  37.     public const int ColumnSize = 2;  
  38. } 

Now we are ready to create/define our EmptyDataTemplate Class. Since all the helper classes are done, the following is the source code for it.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Web.UI.HtmlControls;  
  8. using System.Reflection;  
  9. using System.Text;  
  10. /// <summary>  
  11. /// This is the EmptyDataTemplate Class which when executed will try to create a temporary table  
  12. /// along with the fields specified by the user and the controls to be used defined in the EmptyGridRow class.  
  13. /// </summary>  
  14. public class EmptyGridTemplate : ITemplate  
  15. {  
  16.     private ListItemType _itemType;  
  17.     private const string _openTable = "table";  
  18.     private const string _closeTable = "/table";  
  19.     private const string _openAngularBracket = "<";  
  20.     private const string _closeAngularBracket = ">";  
  21.     private const string _openCell = "td";  
  22.     private const string _closeCell = "/td";  
  23.     private const string _openRow = "tr";  
  24.     private const string _closeRow = "/tr";  
  25.     private const string _space = " ";  
  26.     private const string _doubleQuotes = "\"";  
  27.     private const string _idValueDelimeter = "=";  
  28.     private const string _rowName = "row";  
  29.     private const string _cellName = "cell";  
  30.     private const string _id = "id";  
  31.     private const string _tableID = "table1";  
  32.     private const string _tableStyle = "style=\"width:100%;border:1px solid silver;\"";  
  33.     private const string _colSpan = "colspan=\"2\"";  
  34.     private const string _alignRight = "align=\"right\"";  
  35.     private int _rowCounter = 0, _cellCounter = 0;  
  36.     private List<EmptyGridRow> _lstGridRows = null;  
  37.     private string _redirectPath = string.Empty;  
  38.     //Initialized the update panel at class level so that it can be used any where in the program.  
  39.     private UpdatePanel udpMain = new UpdatePanel()  
  40.     {  
  41.         ID = "udpMain",  
  42.         RenderMode = UpdatePanelRenderMode.Block,  
  43.     };  
  44.     public EmptyGridTemplate(ListItemType item, List<EmptyGridRow> lstRows, string rediredPath)  
  45.     {  
  46.         _lstGridRows = lstRows;  
  47.         _itemType = item;  
  48.         _redirectPath = rediredPath;  
  49.     }  
  50.     /// <summary>  
  51.     /// This function is used for creating rows in the Empty Template Table  
  52.     /// </summary>  
  53.     /// <param name="lstGridRows">List Of Row's Data</param>  
  54.     public void CreateRows(List<EmptyGridRow> lstGridRows)  
  55.     {  
  56.         foreach (EmptyGridRow row in lstGridRows)  
  57.         {  
  58.             Literal ltrlRows = new Literal()  
  59.             {  
  60.                 Text = _openAngularBracket + _openRow + _space + _id +  
  61.                 _idValueDelimeter + _doubleQuotes + _rowName + _rowCounter + _doubleQuotes + _closeAngularBracket  
  62.             };  
  63.             udpMain.ContentTemplateContainer.Controls.Add(ltrlRows);  
  64.             EmptyColumn col = row.Columns;  
  65.             //First Cell of the Table  
  66.             Literal ltrlCells = new Literal()  
  67.             {  
  68.                 Text = _openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +  
  69.                 _rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _closeAngularBracket  
  70.             };  
  71.             udpMain.ContentTemplateContainer.Controls.Add(ltrlCells);  
  72.             //Specify the Column Name into the Literal by using col.ColumnName  
  73.             Literal ltrlCell0 = new Literal()  
  74.             {  
  75.                 Text = col.ColumnName + _openAngularBracket + _closeCell + _closeAngularBracket  
  76.             };  
  77.             //Add the literal to container so that it can be displayed  
  78.             udpMain.ContentTemplateContainer.Controls.Add(ltrlCell0);  
  79.             //Second Cell of the Table  
  80.             _cellCounter++;  
  81.             Literal ltrlCell1 = new Literal()  
  82.             {  
  83.                 Text = _openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +  
  84.                 _rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _closeAngularBracket  
  85.             };  
  86.             udpMain.ContentTemplateContainer.Controls.Add(ltrlCell1);  
  87.             //Add the Control of the Cell          udpMain.ContentTemplateContainer.Controls.Add(col.ColumnControl);  
  88.             Literal ltrlCell1Close = new Literal()  
  89.             {  
  90.                 Text = _openAngularBracket + _closeCell + _closeAngularBracket  
  91.             };  
  92.             _rowCounter++;  
  93.             _cellCounter = 0;  
  94.         }  
  95.         Literal ltrl = new Literal()  
  96.         {  
  97.             //creating new Row  
  98.             Text = _openAngularBracket + _openRow + _space + _id +  
  99.                 _idValueDelimeter + _doubleQuotes + _rowName + _rowCounter + _doubleQuotes + _closeAngularBracket +  
  100.                 //creating new Cell  
  101.                 _openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +  
  102.                 _rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _colSpan + _alignRight + _closeAngularBracket  
  103.         };  
  104.         udpMain.ContentTemplateContainer.Controls.Add(ltrl);  
  105.         Button btnAdd = new Button()  
  106.         {  
  107.             ID = "btnAdd",  
  108.             Text = "Save",  
  109.             CommandName = "AddNew",  
  110.             CausesValidation = false,  
  111.             BackColor = System.Drawing.Color.White,  
  112.             ForeColor = System.Drawing.Color.Black,  
  113.         };  
  114.         if (_redirectPath.Equals("Default.aspx", StringComparison.InvariantCultureIgnoreCase))  
  115.             btnAdd.OnClientClick = "readEmptyGridData();";  
  116.         else  
  117.             btnAdd.Click += new EventHandler(btnAdd_Click);  
  118.         PostBackTrigger trgPostBack = new PostBackTrigger();  
  119.         trgPostBack.ControlID = btnAdd.ID;  
  120.         udpMain.Triggers.Add(trgPostBack);  
  121.         udpMain.ContentTemplateContainer.Controls.Add(btnAdd);  
  122.     }  
  123.     //Button Click Event  
  124.     private void btnAdd_Click(object sender, EventArgs e)  
  125.     {  
  126.         string Data = "";  
  127.         foreach (EmptyGridRow row in _lstGridRows)  
  128.         {  
  129.             if (!row.Columns.IsReadOnly)  
  130.             {  
  131.                 WebControl webControl = (WebControl)row.Columns.ColumnControl;  
  132.                 if (webControl.GetType().Equals(typeof(DropDownList)))  
  133.                 {  
  134.                     DropDownList ddl = (DropDownList)webControl;  
  135.                     Data += ddl.SelectedItem.Text + "|";  
  136.                 }  
  137.                 else if (webControl.GetType().Equals(typeof(TextBox)))  
  138.                 {  
  139.                     TextBox txt = (TextBox)webControl;  
  140.                     Data += txt.Text + "|";  
  141.                 }  
  142.             }  
  143.         }  
  144.         string eName = string.Empty;  
  145.         string eAdd = string.Empty;  
  146.         int eAge = 0;  
  147.         string eCountry = string.Empty;  
  148.         string eDesignation = string.Empty;  
  149.         string[] eData = Data.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);  
  150.         eName = eData[0];  
  151.         eAdd = eData[1];  
  152.         eAge = Convert.ToInt32(eData[2]);  
  153.         eCountry = eData[3];  
  154.         eDesignation = eData[4];  
  155.         DAL objDal = new DAL();  
  156.         objDal.AddRecord(eName, eAdd, eAge, eCountry, eDesignation);  
  157.         HttpContext.Current.Response.Redirect(_redirectPath);  
  158.     }  
  159.     public void InstantiateIn(Control container)  
  160.     {  
  161.         switch (_itemType)  
  162.         {  
  163.             case ListItemType.Header:  
  164.                 Literal ltrlTable = new Literal()  
  165.                 {  
  166.                     Text = _openAngularBracket + _openTable + _space + _id + _idValueDelimeter + _doubleQuotes + _tableID  
  167.                                  + _doubleQuotes + _space + _tableStyle + _closeAngularBracket  
  168.                 };  
  169.                 udpMain.ContentTemplateContainer.Controls.Add(ltrlTable);  
  170.                 CreateRows(_lstGridRows);  
  171.                 container.Controls.Add(udpMain);  
  172.                 break;  
  173.             default:  
  174.                 break;  
  175.         }  
  176.     }  
  177. } 

NOTE: if your observe the code above with in the lime shade, you will find that if the _redirectpage is default.aspx then we are setting the button onclientclick property to some JavaScript function or else we are setting the server side function. For now, just keep this in mind because it will be used at the end of the article where we will try to insert records into the Employee table using an xmlHttpRequest object.

If you observe the source code you will find the following things:-

  1. Our EmptyGridTemplate inherits from the ITemplate class that has one function named InstantiateIn (Control container) that is called automatically when you bind this class to your data control; in our case the GridView control's EmptyDataTemplate.

  2. There is a CreateRow function that accepts a List<EmptyGridRow> class, in other words this list will have all the columns along with the necessary information such as column name to be displayed, whether the column is read-only or not and the control for that column (that is to be used for accepting the input from the user for that column, for instance for accepting a name we will provide a TextBox control in front of the Name column).

  3. In the InstantiateIn function we are using an UpdatePanel, in other words all of our table's data will be placed inside an updatepanel.

  4. After adding all the table data to the updatePanel control, we are adding the update panel to the container control inside the InstantiateIn function.

  5. Finally, on the Button click event we are calling the DAL function to add the record for the Employee.

Now our EmptyGridTemplate is ready, we can make use of it. For testing it let's try to add a page with the name test2.aspx.

NOTE: Remember that our EmptyGridTemplate makes use of UpdatePanel for adding the control on the page. In other words, in our test2.aspx page we will need to add a ScriptManager class.

The following is the markup file of the test2.aspx page:

  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="test2.aspx.cs" Inherits="test2" %>  
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6. </head>  
  7. <body>  
  8.     <form id="form1" runat="server">  
  9.     <div>  
  10.         <asp:ScriptManager ID="ScriptManager1" runat="server">  
  11.         </asp:ScriptManager>  
  12.         <asp:GridView ID="GridView1" runat="server">  
  13.         </asp:GridView>  
  14.     </div>  
  15.     </form>  
  16. </body>  
  17. </html> 

Following is the Source Code of test2.aspx Page.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Data;  
  8. public partial class test2 : System.Web.UI.Page  
  9. {  
  10.     private string _pageName = string.Empty;  
  11.     protected void Page_Load(object sender, EventArgs e)  
  12.     {  
  13.         _pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;  
  14.         System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);  
  15.         _pageName = oInfo.Name;  
  16.         LoadData();  
  17.     }  
  18.     private void LoadData()  
  19.     {  
  20.         DAL objDal = new DAL();  
  21.         DataSet ds = objDal.GetRecords();  
  22.         if (ds != null)  
  23.         {  
  24.             GridView1.DataSource = ds.Tables[0].DefaultView;  
  25.             GridView1.DataBind();  
  26.         }  
  27.         else  
  28.         {  
  29.             //If there is no data present then define the Columns of our EmptyGridRow and add those rows to the EmptyGridTemplate  
  30.             //Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList  
  31.             int[] txtFieldsIndex = { 1, 2, 3, 4 };//here i want textbox to be displayed for column at index position 1,2,3 and 4  
  32.             int[] ddlFieldsIndex = { 5 };//dropdownlist to be displayed for column at index position 5  
  33.             //Define Column names to be displayed in our emptydatatemplate table  
  34.             string[] colNames = { "EID""EName""EAddress""EAge""EDesignation""ECountry" };  
  35.             string errorMsg = "";  
  36.             //Creating array of EmptyColumn  
  37.             EmptyColumn[] cols = new EmptyColumn[colNames.Length];  
  38.             for (byte i = 0; i < cols.Length; i++)  
  39.             {  
  40.                 cols[i] = new EmptyColumn()  
  41.                 {  
  42.                     ColumnName = colNames[i],  
  43.                     IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true;  
  44.                     ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()  
  45.                     {  
  46.                         ID = string.Concat("txt", colNames[i]),  
  47.                         ForeColor = System.Drawing.Color.Black,  
  48.                         Width = new Unit(200),  
  49.                         Height = 15,  
  50.                     }  
  51.                     :  
  52.                     ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()  
  53.                     {  
  54.                         ID = string.Concat("ddl", colNames[i]),  
  55.                         ForeColor = System.Drawing.Color.Black,  
  56.                         Width = new Unit(200),  
  57.                         Height = 20,  
  58.                         AutoPostBack = true,  
  59.                         //defining static list to be displayed inside the dropdownlist  
  60.                         DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }  
  61.                     }  
  62.                     :  
  63.                     (WebControl)new Label()  
  64.                     {  
  65.                         //this column is just for display purpose even if you dont show it there is no issue. I've shown it so that all of us can come to known  
  66.                         // that we can display multiple controls inside the emptydatatemplate table at runtime.  
  67.                         ID = string.Concat("lbl", colNames[i]),  
  68.                         ForeColor = System.Drawing.Color.Black,  
  69.                         Width = new Unit(200),  
  70.                         Text = "0",//by default setting the EID value to zero because it will automatically be calculated inside the insert procedure  
  71.                         Height = 15,  
  72.                     }  
  73.                 };  
  74.             }  
  75.             //Creating list of EmptyGridRows  
  76.             List<EmptyGridRow> lstRows = new List<EmptyGridRow>();  
  77.             foreach (EmptyColumn col in cols)  
  78.             {  
  79.                 lstRows.Add(new EmptyGridRow() { Columns = col });  
  80.             }  
  81.             //ing the list of rows and the listitem type as header and page name to refresh the page to the constructor of our EmptyGridTemplate class  
  82.             EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);  
  83.             //Binding the EmptyGridTemplate to our GridView  
  84.             GridView1.EmptyDataTemplate = objTemplate;  
  85.             GridView1.DataBind();  
  86.         }  
  87.     }  
  88. } 

Finally now we can test the output of our test2.aspx page. If you look at the following diagram, you will find that the column that we declared is displayed as a column heading and also the controls that we used are displayed respective to the columns on the right hand side on the second cell of the row. Since we just now created the Employees, it will not have any records because we are testing the EmptyDataTemplate that will be rendered only if there are no records found in the database.

EmptyDataTemp3.jpg
Now the user can enter the required data and when the user clicks on the Save button all the data entered by the user will be saved in the DB (the Employees table). Let's try to save one record and see the output for it.

EmptyDataTemp4.jpg
Finally now after clicking the SAVE button, you'll find that your data from the EmptyGridTemplate is being saved in your Employees table and you will be able to see the following output:

EmptyDataTemp5.jpg
With this we have completed our work that we want to do. Now let's talk about something relevant to this module. It would be a better approach for us if we check the column, in other words whether the user has entered the proper column name, in other words with no duplication of columns with the same name has been done. Also, for inserting data you can do it directly through JavaScript by making use of the AJAX xmlhttprequest (that we discussed in the NOTE above) or if needed by using Code Behind. In the example above we inserted records by firing the server side button onClick event. Ok now let's try to sort it out one by one.

Checking Column names

For this I've created a class with the name PropertyChecker and one Extension Method CheckItem (that is used on List<EmptyGridRows>) that will check whether the List<EmptyGridRow> has a column with the same name and value that will be added. If it has a column with the same name and value then it will prompt the user with the error details stating the column was already added. The PropertyChecker class is basically checking whether the properties of list elements and that of the targetItem element matches and also their values. If the value of the list elements and that of the targetItem matches then it returns false or else returns true. True denotes the targetItem can be added as a new row in the List<EmptyGridRow> list. It's a generic class.

The following is the source code for it.

Extension Method (CheckItem) Source Code

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. /// <summary>  
  6. /// This class is used for checking whether the item is already added or not.  
  7. /// It makes use for PropertyMatcher class which in turn checks whether  
  8. ///  the column with the specific value has already been added or not.  
  9. /// </summary>  
  10. public static class ExtendedColumnCheck  
  11. {  
  12.     public static bool CheckItem<T, U>(this List<T> lstT, U addItem, out string errorMsg)  
  13.         where T : class,new()  
  14.         where U : class,new()  
  15.     {  
  16.         errorMsg = "";  
  17.         bool status = true;  
  18.         if (addItem == null)  
  19.         {  
  20.             errorMsg = "Added Item cannot be null";  
  21.             return false;  
  22.         }  
  23.         if (lstT.Count == 0)  
  24.             status = true;  
  25.         else  
  26.         {  
  27.             status = PropertyMatcher.MatchPropertyValues<T, U>(lstT, addItem, out errorMsg);  
  28.         }  
  29.         return status;  
  30.     }  
  31. } 

The PropertyMatcher class (that will check whether the property of two objects are the same or not; if the same then return false else true):

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Reflection;  
  6. using System.Collections;  
  7. /// <summary>  
  8. /// It will check whether the item that needs to be added inside the list  
  9. ///has already been added to the list or not by checking the column name and its value  
  10. /// </summary>  
  11. public static class PropertyMatcher  
  12. {  
  13.     public static bool MatchPropertyValues<TSource, TTarget>(List<TSource> lstT, TTarget targetItem, out string errorMsg, string propName = "")  
  14.         where TSource : class  
  15.         where TTarget : class,new()  
  16.     {  
  17.         errorMsg = "";  
  18.         List<TSource> _lstSource = null;  
  19.         TTarget _targetItem = null;  
  20.         //Assing the value of the list and targetItem object to the class Variables.  
  21.         _lstSource = lstT;  
  22.         _targetItem = targetItem;  
  23.         bool status = true;  
  24.         Dictionary<stringobject> dicObj = new Dictionary<stringobject>();  
  25.         Dictionary<stringobject> dicSourceObj = new Dictionary<stringobject>();  
  26.         if (_lstSource == null || _targetItem == null)  
  27.             throw new ArgumentException("Source List or Target Item cannot be null");  
  28.         if (_lstSource.Count == 0)  
  29.             throw new ArgumentException("List Should Contain atleast one item");  
  30.         //Retrieve the targetItem Properties  
  31.         PropertyInfo[] targetProperties = _targetItem.GetType().GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);  
  32.         //Push the targetItem Properties name and value into the Dicobj Dictionary  
  33.         dicObj = targetProperties.ToDictionary(prop => prop.Name, prop => prop.GetValue(_targetItem, null)).ToDictionary(prop => prop.Key, prop => prop.Value);  
  34.         //Retrieve each object from the list  
  35.         foreach (var source in _lstSource)  
  36.         {  
  37.             //Get the property of the object stored in the list  
  38.             //it will return Columns which is the property  
  39.             PropertyInfo[] props = source.GetType().GetProperties();  
  40.             //Store the Column key and value into the Dictionary  
  41.             dicSourceObj = props.ToDictionary(prop => prop.Name,  
  42.                  prop => prop.GetValue(source, null)).  
  43.                  ToDictionary(prop => prop.Key, prop => prop.Value);  
  44.             //Iterate over the items stored in the target DicObj  
  45.             foreach (KeyValuePair<stringobject> keyvalue in dicObj)  
  46.             {  
  47.                 //Iterate ove the items stored in the source Dictionary  
  48.                 //it has key=Columns and value =EmptyHeaderColumn Values stored in the _listSource  
  49.                 foreach (KeyValuePair<stringobject> sourceKeyValue in dicSourceObj)  
  50.                 {  
  51.                     //Get the Property of the source Dictionary i.e. Columns stored in the _listSource  
  52.                     PropertyInfo prop = typeof(TSource).GetProperty(sourceKeyValue.Key);  
  53.                     //Get the Type of the Columns Property i.e. EmptyHeaderColumn stored in the _listSource  
  54.                     Type type = prop.PropertyType;  
  55.                     //Get the actual Properties from the Type type(i.e. EmptyHeaderColumn) stored in the _listSource  
  56.                     PropertyInfo[] mainProps = type.GetProperties();  
  57.                     //Iterate over the properties of the list EmptyGridRows [Columns] Properties  
  58.                     foreach (PropertyInfo p in mainProps)  
  59.                     {  
  60.                         if (!(p.Name.Equals("IsReadOnly", StringComparison.InvariantCultureIgnoreCase) || p.Name.Equals("ColumnControl", StringComparison.InvariantCultureIgnoreCase)))  
  61.                         {  
  62.                             if (p.Name.Equals(keyvalue.Key, StringComparison.InvariantCultureIgnoreCase) && object.Equals(p.GetValue(sourceKeyValue.Value, null), keyvalue.Value))  
  63.                             {  
  64.                                 status = false;  
  65.                                 errorMsg = "Key : " + p.Name + " With Value = " + keyvalue.Value +  
  66.                                 " Already added";  
  67.                                 return status;  
  68.                             }  
  69.                         }  
  70.                     }  
  71.                 }  
  72.             }  
  73.         }  
  74.         return status;  
  75.     }  
  76.  

Now let's try to test it. For testing I've created a web form with the name as test3.aspx.

Mark up code of the Test3.aspx page:

  1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="test3.aspx.cs" Inherits="test3" %>  
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6. </head>  
  7. <body>  
  8.     <form id="form1" runat="server">  
  9.     <div>  
  10.         <asp:GridView ID="GridView1" runat="server">  
  11.         </asp:GridView>  
  12.     </div>  
  13.     </form>  
  14. </body>  
  15. </html> 

Code behind for the same

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Data;  
  8. public partial class test3 : System.Web.UI.Page  
  9. {  
  10.     private string _pageName = string.Empty;  
  11.     protected void Page_Load(object sender, EventArgs e)  
  12.     {  
  13.         _pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;  
  14.         System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);  
  15.         _pageName = oInfo.Name;  
  16.         LoadData();  
  17.     }  
  18.     private void LoadData()  
  19.     {  
  20.         DAL objDal = new DAL();  
  21.         DataSet ds = objDal.GetRecords();  
  22.         if (ds != null)  
  23.         {  
  24.             GridView1.DataSource = ds.Tables[0].DefaultView;  
  25.             GridView1.DataBind();  
  26.         }  
  27.         else  
  28.         {  
  29.             bool tableStatus = true;  
  30.             //Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList  
  31.             int[] txtFieldsIndex = { 1, 2, 3, 4 };  
  32.             int[] ddlFieldsIndex = { 5 };  
  33.             //Define Column names  
  34.            //here we are purposely adding EName twice so in such case we should get an error message  
  35.             string[] colNames = { "EID""EName""EName""EAge""EDesignation""ECountry" };  
  36.             string errorMsg = "";  
  37.             EmptyColumn[] cols = new EmptyColumn[colNames.Length];  
  38.             for (byte i = 0; i < cols.Length; i++)  
  39.             {  
  40.                 cols[i] = new EmptyColumn()  
  41.                 {  
  42.                     ColumnName = colNames[i],  
  43.                     IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true,  
  44.                     ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()  
  45.                     {  
  46.                         ID = string.Concat("txt", colNames[i]),  
  47.                         ForeColor = System.Drawing.Color.Black,  
  48.                         Width = new Unit(200),  
  49.                         Height = 15,  
  50.                     }  
  51.                     :  
  52.                     ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()  
  53.                     {  
  54.                         ID = string.Concat("ddl", colNames[i]),  
  55.                         ForeColor = System.Drawing.Color.Black,  
  56.                         Width = new Unit(200),  
  57.                         Height = 20,  
  58.                         AutoPostBack = true,  
  59.                         DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }  
  60.                     }  
  61.                     :  
  62.                     (WebControl)new Label()  
  63.                     {  
  64.                         ID = string.Concat("lbl", colNames[i]),  
  65.                         ForeColor = System.Drawing.Color.Black,  
  66.                         Width = new Unit(200),  
  67.                         Text = "0",  
  68.                         Height = 15,  
  69.                     }  
  70.                 };  
  71.             }  
  72.             //Creating list of EmptyGridRows  
  73.             List<EmptyGridRow> lstRows = new List<EmptyGridRow>();  
  74.             foreach (EmptyColumn col in cols)  
  75.             {  
  76.                 //Checking whether the column name has already being added or not  
  77.                 if (lstRows.CheckItem<EmptyGridRow, EmptyColumn>(col, out errorMsg))  
  78.                     lstRows.Add(new EmptyGridRow() { Columns = col });  
  79.                 else  
  80.                 {  
  81.                     tableStatus = false;  
  82.                     ClientScript.RegisterStartupScript(this.GetType(), "error""<script>alert('" + errorMsg + "');</script>");  
  83.                 }  
  84.             }  
  85.             if (tableStatus == true)  
  86.             {  
  87.                 //Binding the EmptyTemplate to our GridView  
  88.                 EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);  
  89.                 GridView1.EmptyDataTemplate = objTemplate;  
  90.                 GridView1.DataBind();  
  91.             }  
  92.         }  
  93.     }  
  94. } 

Now let's run the test3.aspx page and see the following output. Before running it, we will truncate the Employees table so that there are no records and our EmptyGridTemplate can be applied to the GridView's EmptyDataTemplate. Now when you run your test3.aspx page you'll see the following output.

EmptyDataTemp6.jpg

By looking at the following output we are sure that our propertymatcher class is working fine.

Now for the last part of the article, in other words the insertion of data using an xmlhttprequest object. For this I'm adding an external js file with the name jsHelper.js and also the AjaxHelper.aspx page that will be called by an xmlHttpRequest object.

The following is the code for that:

External Js File (jsHelper.js)

  1. var grid = null;  
  2. var elements = null;  
  3. var name = null;  
  4. var address = null;  
  5. var designation = null;  
  6. var country = null;  
  7. var age = 0;  
  8. var eid = 0;  
  9. var eData = "";  
  10. //Create XMLHttpRequest object  
  11. var httpRequest = null;  
  12. function getXMLHttpRequest() {  
  13.     if (window.ActiveXObject) {  
  14.         try {  
  15.             return new ActiveXObject("Msxml2.XMLHTTP");  
  16.         } catch (e) {  
  17.             try {  
  18.                 return new ActiveXObject("Microsoft.XMLHTTP");  
  19.             } catch (e1) {  
  20.                 return null;  
  21.             }  
  22.         }  
  23.     } else if (window.XMLHttpRequest) {  
  24.         return new XMLHttpRequest();  
  25.     } else {  
  26.         return null;  
  27.     }  
  28. }  
  29. //Check whether the request is from Firefox browser  
  30. function isFireFox() {  
  31.     return navigator.userAgent;  
  32. }  
  33. //Read Data From GridView  
  34. function readEmptyGridData() {  
  35.     try {  
  36.         if (elements != null)  
  37.             grid = document.getElementById(elements.varGridView);  
  38.         var userNavigator = isFireFox();  
  39.         //Accessing our UpdatePanel which we created in our EmptyDataTemplate  
  40.         var emptyUpdatePanel = grid.rows[0].cells[0].childNodes[0]; //#table1 is the id of the table Control  
  41.         //Accessing the table control created in our EmptyDataTemplate  
  42.         var emptyTable = emptyUpdatePanel.childNodes[1];  
  43.         var rowsLength = emptyTable.rows.length;  
  44.         for (var rowCounter = 0; rowCounter < rowsLength - 1; rowCounter++) {  
  45.             for (var cellCounter = 0; cellCounter < emptyTable.rows[rowCounter].cells.length; cellCounter++) {  
  46.                 if (userNavigator.indexOf("Firefox") != -1) {  
  47.                     eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;  
  48.                 }  
  49.                 else {  
  50.                     //For accessing the textContent of the First Column Cells Names  
  51.                     if (cellCounter == 0) {  
  52.                         eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;  
  53.                         eData += "=";  
  54.                     }  
  55.                     //For accessing the value within the TextBox  
  56.                     else {  
  57.                         //This is done for accesing the text of the Empid and value as  Zero because over there are no control we have used  
  58.                         if (emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].value != undefined)  
  59.                             eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].value; //for accessing the controls from TextBox or Some other control  
  60.                         else//that's why we will have to access the values by using textContent  
  61.                             eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;  
  62.                     }  
  63.                 }  
  64.             }  
  65.             eData += "|";  
  66.         }  
  67.         httpRequest = getXMLHttpRequest();  
  68.         httpRequest.open("POST""Ajax/AjaxHelper.aspx?eData=" + eData, true);  
  69.         //    //Send the proper header information along with the request  
  70.         //    httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");  
  71.         //    httpRequest.setRequestHeader("Content-length", param.length);  
  72.         //    httpRequest.setRequestHeader("Connection", "close");  
  73.         //Setup the callback function  
  74.         httpRequest.onreadystatechange = onSuccess;  
  75.         httpRequest.send();  
  76.         return false;  
  77.     }  
  78.     catch (e) {  
  79.         alert(e.Message);  
  80.     }  
  81. }  
  82. /* 
  83. If data is inserted successfully then refresh the page 
  84. */  
  85. function onSuccess() {  
  86.     //checking for the readyState and status of the httpRequest object  
  87.     if (httpRequest.readyState == 4 && httpRequest.status == 200) {  
  88.         //  finally getting the responseText of the httpRequest object  
  89.         var result = httpRequest.responseText;  
  90.         if (result == "Successfull") {  
  91.             window.location.href = window.location.href; //refresh the page  
  92.         }  
  93.         else if (result == "Error")  
  94.             alert('Error Saving Data'); //else display an error message  
  95.     }  
  96. }  
  97. /* 
  98. This function is used for handling errors 
  99. */  
  100. function onError(result) {  
  101.     // ajax call failed  
  102.     alert('Error ' + result.status + ': ' + result.statusText);  
  103. }

The AjaxHelper.js file is placed inside the Ajax folder within the application. The following is the markup and code behind file for that:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Data;  
  8. using System.Data.OracleClient;  
  9. public partial class Ajax_AjaxHelper : System.Web.UI.Page  
  10. {  
  11.     const string _dbCon = "DATA SOURCE=DHQMDB;WORD=hqm321;PERSIST SECURITY INFO=True;USER ID=HQM_ADMIN";  
  12.     OracleConnection con;  
  13.     OracleCommand cmd;  
  14.     protected void Page_Load(object sender, EventArgs e)  
  15.     {  
  16.         if (Request.QueryString.Count > 0 && Request.QueryString["eData"] != null)  
  17.         {  
  18.             AddDataToEmployee(Request.QueryString["eData"].ToString());  
  19.         }  
  20.     }  
  21.     /// <summary>  
  22.     /// This function is used for adding record  to the employee table.  
  23.     /// </summary>  
  24.     /// <param name="eData">Data appended by using | operator</param>  
  25.     /// <returns>returns string as Successfull or Error</returns>  
  26.     private string AddDataToEmployee(string eData)  
  27.     {  
  28.         //Spliting the value by using | operator and removing the empty entries  
  29.         string[] arr = eData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);  
  30.         List<string> lstValues = new List<string>();  
  31.         string value = "", returnValue = "";  
  32.         foreach (string str in arr)  
  33.         {  
  34.             //Accessing the value from the array that's why the index 1 is specified. because over here the value are in the  
  35.             //form of ColName=Value so in our arr items will be store like the following  
  36.             //{Empid=value},{EName=value},{Ecountry=value} like so on.  
  37.             value = str.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1];  
  38.             lstValues.Add(value);  
  39.         }  
  40.         DAL obj = new DAL();  
  41.         int rows = obj.AddRecord(lstValues[1], lstValues[2], Convert.ToInt32(lstValues[3]), lstValues[4], lstValues[5]);  
  42.         if (rows > 0)  
  43.             returnValue = "Successfull";  
  44.         else  
  45.             returnValue = "Error";  
  46.         return returnValue;  
  47.     }  
  48. } 

Now to test it I've added a page with the name Default.aspx.

On the Markup page (the default.aspx page) we just took a gridview control.

Default.aspx Code behind

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.UI;  
  6. using System.Web.UI.WebControls;  
  7. using System.Configuration;  
  8. using System.Data.OracleClient;  
  9. using System.Data;  
  10. public partial class _Default : System.Web.UI.Page  
  11. {  
  12.     private string _pageName = string.Empty;  
  13.     protected void Page_Load(object sender, EventArgs e)  
  14.     {  
  15.         _pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;  
  16.         System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);  
  17.         _pageName = oInfo.Name;  
  18.         LoadData();  
  19.     }  
  20.     private void LoadData()  
  21.     {  
  22.         DAL objDal = new DAL();  
  23.         DataSet ds = objDal.GetRecords();  
  24.         if (ds != null)  
  25.         {  
  26.             GridView1.DataSource = ds.Tables[0].DefaultView;  
  27.             GridView1.DataBind();  
  28.         }  
  29.         else  
  30.         {  
  31.             bool tableStatus = true;  
  32.             //Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList  
  33.             int[] txtFieldsIndex = { 1, 2, 3, 4 };  
  34.             int[] ddlFieldsIndex = { 5 };  
  35.             //Define Column names  
  36.             string[] colNames = { "EID""EName""EAddress""EAge""EDesignation""ECountry" };  
  37.             string errorMsg = "";  
  38.             EmptyColumn[] cols = new EmptyColumn[colNames.Length];  
  39.             for (byte i = 0; i < cols.Length; i++)  
  40.             {  
  41.                 cols[i] = new EmptyColumn()  
  42.                 {  
  43.                     ColumnName = colNames[i],  
  44.                     IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true,  
  45.                     ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()  
  46.                     {  
  47.                         ID = string.Concat("txt", colNames[i]),  
  48.                         ForeColor = System.Drawing.Color.Black,  
  49.                         Width = new Unit(200),  
  50.                         Height = 15,  
  51.                     }  
  52.                     :  
  53.                     ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()  
  54.                     {  
  55.                         ID = string.Concat("ddl", colNames[i]),  
  56.                         ForeColor = System.Drawing.Color.Black,  
  57.                         Width = new Unit(200),  
  58.                         Height = 20,  
  59.                         AutoPostBack = true,  
  60.                         DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }  
  61.                     }  
  62.                     :  
  63.                     (WebControl)new Label()  
  64.                     {  
  65.                         ID = string.Concat("lbl", colNames[i]),  
  66.                         ForeColor = System.Drawing.Color.Black,  
  67.                         Width = new Unit(200),  
  68.                         Text = "0",  
  69.                         Height = 15,  
  70.                     }  
  71.                 };  
  72.             }  
  73.             //Creating list of EmptyGridRows  
  74.             List<EmptyGridRow> lstRows = new List<EmptyGridRow>();  
  75.             foreach (EmptyColumn col in cols)  
  76.             {  
  77.                 //Checking whether the column name has already being added or not  
  78.                 if (lstRows.CheckItem<EmptyGridRow, EmptyColumn>(col, out errorMsg))  
  79.                     lstRows.Add(new EmptyGridRow() { Columns = col });  
  80.                 else  
  81.                 {  
  82.                     tableStatus = false;  
  83.                     ClientScript.RegisterStartupScript(this.GetType(), "error""<script>alert('" + errorMsg + "');</script>");  
  84.                 }  
  85.             }  
  86.             if (tableStatus == true)  
  87.             {  
  88.                 //Binding the EmptyTemplate to our GridView  
  89.                 EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);  
  90.                 GridView1.EmptyDataTemplate = objTemplate;  
  91.                 GridView1.DataBind();  
  92.             }  
  93.         }  
  94.     }  
  95. } 

Let's try to run the Default.aspx page. Before running we will truncate the Employees table so that there are no records and our EmptyGridTemplate can be applied to the GridView's EmptyDataTemplate. Now when you run your Default.aspx page you'll see the following output.

EmptyDataTemp7.jpg
On the Button click event it will class the jsHelper function that will insert the data into my Employees table by making use of the AjaxHeper.aspx file and you will get the following output:

EmptyDataTemp8.jpg
I hope you all liked the article.