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:
create table Employees
(
EId int not null,
EName varchar(30),
EAddress varchar(30),
EAge Number,
ECountry varchar(30),
EDesignation varchar(30)
)
//For Accessing the Data stored in Employees Table
create or replace procedure prcGetEmployees
(
temp_cursor out sys_refCursor
)
as
begin
open temp_cursor for
select * from Employees;
end;
//For Inserting the Data in Employees Table
create or replace procedure prcAddEmp
(
v_name varchar2,
v_address varchar2,
n_age number,
v_country varchar2,
v_designation varchar2
)
as
v_id number:=0;
begin
select count(*) into v_id from Employees;
v_id:=v_id+1;
insert into Employees
values (v_id,v_name,v_address,n_age,v_country,v_designation);
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
Test.aspx.cs Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
private void LoadData()
{
DAL objDal = new DAL();
DataSet ds = objDal.GetRecords();
if (ds != null)
{
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
}
}
Now when I try to run the file all I get is a blank page like the following.
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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using System.Web.UI;
/// <summary>
/// This class will act a as column of EmptyDataTemplate Table.
///This class is used by EmptyGridRow class
/// </summary>
public class EmptyColumn
{
//specifies the column text to be displayed
public string ColumnName { get; set; }
//specifies whether the column is ready only or not
public bool IsReadOnly { get; set; }
//the control to use for the column
public WebControl ColumnControl { get; set; }
//setting the default control as Label.
public EmptyColumn()
{
ColumnControl = new Label();
}
}
/// <summary>
/// This class act as a row of EmptyDataTemplate Table.
///This class is used by EmptyGridTemplate.
/// </summary>
public class EmptyGridRow
{
//Specifies EmptyColumn Properties
public EmptyColumn Columns { get; set; }
//the default cell size within a row. i.e. Maximum 2 cells will be there inside a row
public const int ColumnSize = 2;
}
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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Reflection;
using System.Text;
/// <summary>
/// This is the EmptyDataTemplate Class which when executed will try to create a temporary table
/// along with the fields specified by the user and the controls to be used defined in the EmptyGridRow class.
/// </summary>
public class EmptyGridTemplate : ITemplate
{
private ListItemType _itemType;
private const string _openTable = "table";
private const string _closeTable = "/table";
private const string _openAngularBracket = "<";
private const string _closeAngularBracket = ">";
private const string _openCell = "td";
private const string _closeCell = "/td";
private const string _openRow = "tr";
private const string _closeRow = "/tr";
private const string _space = " ";
private const string _doubleQuotes = "\"";
private const string _idValueDelimeter = "=";
private const string _rowName = "row";
private const string _cellName = "cell";
private const string _id = "id";
private const string _tableID = "table1";
private const string _tableStyle = "style=\"width:100%;border:1px solid silver;\"";
private const string _colSpan = "colspan=\"2\"";
private const string _alignRight = "align=\"right\"";
private int _rowCounter = 0, _cellCounter = 0;
private List<EmptyGridRow> _lstGridRows = null;
private string _redirectPath = string.Empty;
//Initialized the update panel at class level so that it can be used any where in the program.
private UpdatePanel udpMain = new UpdatePanel()
{
ID = "udpMain",
RenderMode = UpdatePanelRenderMode.Block,
};
public EmptyGridTemplate(ListItemType item, List<EmptyGridRow> lstRows, string rediredPath)
{
_lstGridRows = lstRows;
_itemType = item;
_redirectPath = rediredPath;
}
/// <summary>
/// This function is used for creating rows in the Empty Template Table
/// </summary>
/// <param name="lstGridRows">List Of Row's Data</param>
public void CreateRows(List<EmptyGridRow> lstGridRows)
{
foreach (EmptyGridRow row in lstGridRows)
{
Literal ltrlRows = new Literal()
{
Text = _openAngularBracket + _openRow + _space + _id +
_idValueDelimeter + _doubleQuotes + _rowName + _rowCounter + _doubleQuotes + _closeAngularBracket
};
udpMain.ContentTemplateContainer.Controls.Add(ltrlRows);
EmptyColumn col = row.Columns;
//First Cell of the Table
Literal ltrlCells = new Literal()
{
Text = _openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +
_rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _closeAngularBracket
};
udpMain.ContentTemplateContainer.Controls.Add(ltrlCells);
//Specify the Column Name into the Literal by using col.ColumnName
Literal ltrlCell0 = new Literal()
{
Text = col.ColumnName + _openAngularBracket + _closeCell + _closeAngularBracket
};
//Add the literal to container so that it can be displayed
udpMain.ContentTemplateContainer.Controls.Add(ltrlCell0);
//Second Cell of the Table
_cellCounter++;
Literal ltrlCell1 = new Literal()
{
Text = _openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +
_rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _closeAngularBracket
};
udpMain.ContentTemplateContainer.Controls.Add(ltrlCell1);
//Add the Control of the Cell
udpMain.ContentTemplateContainer.Controls.Add(col.ColumnControl);
Literal ltrlCell1Close = new Literal()
{
Text = _openAngularBracket + _closeCell + _closeAngularBracket
};
_rowCounter++;
_cellCounter = 0;
}
Literal ltrl = new Literal()
{
//creating new Row
Text = _openAngularBracket + _openRow + _space + _id +
_idValueDelimeter + _doubleQuotes + _rowName + _rowCounter + _doubleQuotes + _closeAngularBracket +
//creating new Cell
_openAngularBracket + _openCell + _space + _id + _idValueDelimeter + _doubleQuotes +
_rowName + _rowCounter + _cellName + _cellCounter + _doubleQuotes + _colSpan + _alignRight + _closeAngularBracket
};
udpMain.ContentTemplateContainer.Controls.Add(ltrl);
Button btnAdd = new Button()
{
ID = "btnAdd",
Text = "Save",
CommandName = "AddNew",
CausesValidation = false,
BackColor = System.Drawing.Color.White,
ForeColor = System.Drawing.Color.Black,
};
if (_redirectPath.Equals("Default.aspx", StringComparison.InvariantCultureIgnoreCase))
btnAdd.OnClientClick = "readEmptyGridData();";
else
btnAdd.Click += new EventHandler(btnAdd_Click);
PostBackTrigger trgPostBack = new PostBackTrigger();
trgPostBack.ControlID = btnAdd.ID;
udpMain.Triggers.Add(trgPostBack);
udpMain.ContentTemplateContainer.Controls.Add(btnAdd);
}
//Button Click Event
private void btnAdd_Click(object sender, EventArgs e)
{
string Data = "";
foreach (EmptyGridRow row in _lstGridRows)
{
if (!row.Columns.IsReadOnly)
{
WebControl webControl = (WebControl)row.Columns.ColumnControl;
if (webControl.GetType().Equals(typeof(DropDownList)))
{
DropDownList ddl = (DropDownList)webControl;
Data += ddl.SelectedItem.Text + "|";
}
else if (webControl.GetType().Equals(typeof(TextBox)))
{
TextBox txt = (TextBox)webControl;
Data += txt.Text + "|";
}
}
}
string eName = string.Empty;
string eAdd = string.Empty;
int eAge = 0;
string eCountry = string.Empty;
string eDesignation = string.Empty;
string[] eData = Data.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
eName = eData[0];
eAdd = eData[1];
eAge = Convert.ToInt32(eData[2]);
eCountry = eData[3];
eDesignation = eData[4];
DAL objDal = new DAL();
objDal.AddRecord(eName, eAdd, eAge, eCountry, eDesignation);
HttpContext.Current.Response.Redirect(_redirectPath);
}
public void InstantiateIn(Control container)
{
switch (_itemType)
{
case ListItemType.Header:
Literal ltrlTable = new Literal()
{
Text = _openAngularBracket + _openTable + _space + _id + _idValueDelimeter + _doubleQuotes + _tableID
+ _doubleQuotes + _space + _tableStyle + _closeAngularBracket
};
udpMain.ContentTemplateContainer.Controls.Add(ltrlTable);
CreateRows(_lstGridRows);
container.Controls.Add(udpMain);
break;
default:
break;
}
}
}
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:-
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.
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).
In the InstantiateIn function we are using an UpdatePanel, in other words all of our table's data will be placed inside an updatepanel.
After adding all the table data to the updatePanel control, we are adding the update panel to the container control inside the InstantiateIn function.
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:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test2.aspx.cs" Inherits="test2" %>
<!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>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</div>
</form>
</body>
</html>
Following is the Source Code of test2.aspx Page.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class test2 : System.Web.UI.Page
{
private string _pageName = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
_pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);
_pageName = oInfo.Name;
LoadData();
}
private void LoadData()
{
DAL objDal = new DAL();
DataSet ds = objDal.GetRecords();
if (ds != null)
{
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
else
{
//If there is no data present then define the Columns of our EmptyGridRow and add those rows to the EmptyGridTemplate
//Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList
int[] txtFieldsIndex = { 1, 2, 3, 4 };//here i want textbox to be displayed for column at index position 1,2,3 and 4
int[] ddlFieldsIndex = { 5 };//dropdownlist to be displayed for column at index position 5
//Define Column names to be displayed in our emptydatatemplate table
string[] colNames = { "EID", "EName", "EAddress", "EAge", "EDesignation", "ECountry" };
string errorMsg = "";
//Creating array of EmptyColumn
EmptyColumn[] cols = new EmptyColumn[colNames.Length];
for (byte i = 0; i < cols.Length; i++)
{
cols[i] = new EmptyColumn()
{
ColumnName = colNames[i],
IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true;
ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()
{
ID = string.Concat("txt", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 15,
}
:
ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()
{
ID = string.Concat("ddl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 20,
AutoPostBack = true,
//defining static list to be displayed inside the dropdownlist
DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }
}
:
(WebControl)new Label()
{
//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
// that we can display multiple controls inside the emptydatatemplate table at runtime.
ID = string.Concat("lbl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Text = "0",//by default setting the EID value to zero because it will automatically be calculated inside the insert procedure
Height = 15,
}
};
}
//Creating list of EmptyGridRows
List<EmptyGridRow> lstRows = new List<EmptyGridRow>();
foreach (EmptyColumn col in cols)
{
lstRows.Add(new EmptyGridRow() { Columns = col });
}
//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
EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);
//Binding the EmptyGridTemplate to our GridView
GridView1.EmptyDataTemplate = objTemplate;
GridView1.DataBind();
}
}
}
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.
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.
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:
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// This class is used for checking whether the item is already added or not.
/// It makes use for PropertyMatcher class which in turn checks whether
/// the column with the specific value has already been added or not.
/// </summary>
public static class ExtendedColumnCheck
{
public static bool CheckItem<T, U>(this List<T> lstT, U addItem, out string errorMsg)
where T : class,new()
where U : class,new()
{
errorMsg = "";
bool status = true;
if (addItem == null)
{
errorMsg = "Added Item cannot be null";
return false;
}
if (lstT.Count == 0)
status = true;
else
{
status = PropertyMatcher.MatchPropertyValues<T, U>(lstT, addItem, out errorMsg);
}
return status;
}
}
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):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Collections;
/// <summary>
/// It will check whether the item that needs to be added inside the list
///has already been added to the list or not by checking the column name and its value
/// </summary>
public static class PropertyMatcher
{
public static bool MatchPropertyValues<TSource, TTarget>(List<TSource> lstT, TTarget targetItem, out string errorMsg, string propName = "")
where TSource : class
where TTarget : class,new()
{
errorMsg = "";
List<TSource> _lstSource = null;
TTarget _targetItem = null;
//Assing the value of the list and targetItem object to the class Variables.
_lstSource = lstT;
_targetItem = targetItem;
bool status = true;
Dictionary<string, object> dicObj = new Dictionary<string, object>();
Dictionary<string, object> dicSourceObj = new Dictionary<string, object>();
if (_lstSource == null || _targetItem == null)
throw new ArgumentException("Source List or Target Item cannot be null");
if (_lstSource.Count == 0)
throw new ArgumentException("List Should Contain atleast one item");
//Retrieve the targetItem Properties
PropertyInfo[] targetProperties = _targetItem.GetType().GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
//Push the targetItem Properties name and value into the Dicobj Dictionary
dicObj = targetProperties.ToDictionary(prop => prop.Name, prop => prop.GetValue(_targetItem, null)).ToDictionary(prop => prop.Key, prop => prop.Value);
//Retrieve each object from the list
foreach (var source in _lstSource)
{
//Get the property of the object stored in the list
//it will return Columns which is the property
PropertyInfo[] props = source.GetType().GetProperties();
//Store the Column key and value into the Dictionary
dicSourceObj = props.ToDictionary(prop => prop.Name,
prop => prop.GetValue(source, null)).
ToDictionary(prop => prop.Key, prop => prop.Value);
//Iterate over the items stored in the target DicObj
foreach (KeyValuePair<string, object> keyvalue in dicObj)
{
//Iterate ove the items stored in the source Dictionary
//it has key=Columns and value =EmptyHeaderColumn Values stored in the _listSource
foreach (KeyValuePair<string, object> sourceKeyValue in dicSourceObj)
{
//Get the Property of the source Dictionary i.e. Columns stored in the _listSource
PropertyInfo prop = typeof(TSource).GetProperty(sourceKeyValue.Key);
//Get the Type of the Columns Property i.e. EmptyHeaderColumn stored in the _listSource
Type type = prop.PropertyType;
//Get the actual Properties from the Type type(i.e. EmptyHeaderColumn) stored in the _listSource
PropertyInfo[] mainProps = type.GetProperties();
//Iterate over the properties of the list EmptyGridRows [Columns] Properties
foreach (PropertyInfo p in mainProps)
{
if (!(p.Name.Equals("IsReadOnly", StringComparison.InvariantCultureIgnoreCase) || p.Name.Equals("ColumnControl", StringComparison.InvariantCultureIgnoreCase)))
{
if (p.Name.Equals(keyvalue.Key, StringComparison.InvariantCultureIgnoreCase) && object.Equals(p.GetValue(sourceKeyValue.Value, null), keyvalue.Value))
{
status = false;
errorMsg = "Key : " + p.Name + " With Value = " + keyvalue.Value +
" Already added";
return status;
}
}
}
}
}
}
return status;
}
}
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:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test3.aspx.cs" Inherits="test3" %>
<!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>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</div>
</form>
</body>
</html>
Code behind for the same
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class test3 : System.Web.UI.Page
{
private string _pageName = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
_pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);
_pageName = oInfo.Name;
LoadData();
}
private void LoadData()
{
DAL objDal = new DAL();
DataSet ds = objDal.GetRecords();
if (ds != null)
{
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
else
{
bool tableStatus = true;
//Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList
int[] txtFieldsIndex = { 1, 2, 3, 4 };
int[] ddlFieldsIndex = { 5 };
//Define Column names
//here we are purposely adding EName twice so in such case we should get an error message
string[] colNames = { "EID", "EName", "EName", "EAge", "EDesignation", "ECountry" };
string errorMsg = "";
EmptyColumn[] cols = new EmptyColumn[colNames.Length];
for (byte i = 0; i < cols.Length; i++)
{
cols[i] = new EmptyColumn()
{
ColumnName = colNames[i],
IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true,
ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()
{
ID = string.Concat("txt", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 15,
}
:
ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()
{
ID = string.Concat("ddl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 20,
AutoPostBack = true,
DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }
}
:
(WebControl)new Label()
{
ID = string.Concat("lbl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Text = "0",
Height = 15,
}
};
}
//Creating list of EmptyGridRows
List<EmptyGridRow> lstRows = new List<EmptyGridRow>();
foreach (EmptyColumn col in cols)
{
//Checking whether the column name has already being added or not
if (lstRows.CheckItem<EmptyGridRow, EmptyColumn>(col, out errorMsg))
lstRows.Add(new EmptyGridRow() { Columns = col });
else
{
tableStatus = false;
ClientScript.RegisterStartupScript(this.GetType(), "error", "<script>alert('" + errorMsg + "');</script>");
}
}
if (tableStatus == true)
{
//Binding the EmptyTemplate to our GridView
EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);
GridView1.EmptyDataTemplate = objTemplate;
GridView1.DataBind();
}
}
}
}
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.
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)
var grid = null;
var elements = null;
var name = null;
var address = null;
var designation = null;
var country = null;
var age = 0;
var eid = 0;
var eData = "";
//Create XMLHttpRequest object
var httpRequest = null;
function getXMLHttpRequest() {
if (window.ActiveXObject) {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e1) {
return null;
}
}
} else if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return null;
}
}
//Check whether the request is from Firefox browser
function isFireFox() {
return navigator.userAgent;
}
//Read Data From GridView
function readEmptyGridData() {
try {
if (elements != null)
grid = document.getElementById(elements.varGridView);
var userNavigator = isFireFox();
//Accessing our UpdatePanel which we created in our EmptyDataTemplate
var emptyUpdatePanel = grid.rows[0].cells[0].childNodes[0]; //#table1 is the id of the table Control
//Accessing the table control created in our EmptyDataTemplate
var emptyTable = emptyUpdatePanel.childNodes[1];
var rowsLength = emptyTable.rows.length;
for (var rowCounter = 0; rowCounter < rowsLength - 1; rowCounter++) {
for (var cellCounter = 0; cellCounter < emptyTable.rows[rowCounter].cells.length; cellCounter++) {
if (userNavigator.indexOf("Firefox") != -1) {
eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;
}
else {
//For accessing the textContent of the First Column Cells Names
if (cellCounter == 0) {
eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;
eData += "=";
}
//For accessing the value within the TextBox
else {
//This is done for accesing the text of the Empid and value as Zero because over there are no control we have used
if (emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].value != undefined)
eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].value; //for accessing the controls from TextBox or Some other control
else//that's why we will have to access the values by using textContent
eData += emptyTable.rows[rowCounter].cells[cellCounter].childNodes[0].textContent;
}
}
}
eData += "|";
}
httpRequest = getXMLHttpRequest();
httpRequest.open("POST", "Ajax/AjaxHelper.aspx?eData=" + eData, true);
// //Send the proper header information along with the request
// httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// httpRequest.setRequestHeader("Content-length", param.length);
// httpRequest.setRequestHeader("Connection", "close");
//Setup the callback function
httpRequest.onreadystatechange = onSuccess;
httpRequest.send();
return false;
}
catch (e) {
alert(e.Message);
}
}
/*
If data is inserted successfully then refresh the page
*/
function onSuccess() {
//checking for the readyState and status of the httpRequest object
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
// finally getting the responseText of the httpRequest object
var result = httpRequest.responseText;
if (result == "Successfull") {
window.location.href = window.location.href; //refresh the page
}
else if (result == "Error")
alert('Error Saving Data'); //else display an error message
}
}
/*
This function is used for handling errors
*/
function onError(result) {
// ajax call failed
alert('Error ' + result.status + ': ' + result.statusText);
}
The AjaxHelper.js file is placed inside the Ajax folder within the application. The following is the markup and code behind file for that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.OracleClient;
public partial class Ajax_AjaxHelper : System.Web.UI.Page
{
const string _dbCon = "DATA SOURCE=DHQMDB;WORD=hqm321;PERSIST SECURITY INFO=True;USER ID=HQM_ADMIN";
OracleConnection con;
OracleCommand cmd;
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString.Count > 0 && Request.QueryString["eData"] != null)
{
AddDataToEmployee(Request.QueryString["eData"].ToString());
}
}
/// <summary>
/// This function is used for adding record to the employee table.
/// </summary>
/// <param name="eData">Data appended by using | operator</param>
/// <returns>returns string as Successfull or Error</returns>
private string AddDataToEmployee(string eData)
{
//Spliting the value by using | operator and removing the empty entries
string[] arr = eData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
List<string> lstValues = new List<string>();
string value = "", returnValue = "";
foreach (string str in arr)
{
//Accessing the value from the array that's why the index 1 is specified. because over here the value are in the
//form of ColName=Value so in our arr items will be store like the following
//{Empid=value},{EName=value},{Ecountry=value} like so on.
value = str.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1];
lstValues.Add(value);
}
DAL obj = new DAL();
int rows = obj.AddRecord(lstValues[1], lstValues[2], Convert.ToInt32(lstValues[3]), lstValues[4], lstValues[5]);
if (rows > 0)
returnValue = "Successfull";
else
returnValue = "Error";
return returnValue;
}
}
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Data.OracleClient;
using System.Data;
public partial class _Default : System.Web.UI.Page
{
private string _pageName = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
_pageName = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
System.IO.FileInfo oInfo = new System.IO.FileInfo(_pageName);
_pageName = oInfo.Name;
LoadData();
}
private void LoadData()
{
DAL objDal = new DAL();
DataSet ds = objDal.GetRecords();
if (ds != null)
{
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
else
{
bool tableStatus = true;
//Define controls index position for eg at index 1,2,3,5 textbox will be there and at index 4 DropDownList
int[] txtFieldsIndex = { 1, 2, 3, 4 };
int[] ddlFieldsIndex = { 5 };
//Define Column names
string[] colNames = { "EID", "EName", "EAddress", "EAge", "EDesignation", "ECountry" };
string errorMsg = "";
EmptyColumn[] cols = new EmptyColumn[colNames.Length];
for (byte i = 0; i < cols.Length; i++)
{
cols[i] = new EmptyColumn()
{
ColumnName = colNames[i],
IsReadOnly = txtFieldsIndex.Contains(i) == true ? false : ddlFieldsIndex.Contains(i) == true ? false : true,
ColumnControl = txtFieldsIndex.Contains(i) == true ? new TextBox()
{
ID = string.Concat("txt", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 15,
}
:
ddlFieldsIndex.Contains(i) == true ? (WebControl)new DropDownList()
{
ID = string.Concat("ddl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Height = 20,
AutoPostBack = true,
DataSource = new ListItemCollection { new ListItem("Select"), new ListItem("India"), new ListItem("China") }
}
:
(WebControl)new Label()
{
ID = string.Concat("lbl", colNames[i]),
ForeColor = System.Drawing.Color.Black,
Width = new Unit(200),
Text = "0",
Height = 15,
}
};
}
//Creating list of EmptyGridRows
List<EmptyGridRow> lstRows = new List<EmptyGridRow>();
foreach (EmptyColumn col in cols)
{
//Checking whether the column name has already being added or not
if (lstRows.CheckItem<EmptyGridRow, EmptyColumn>(col, out errorMsg))
lstRows.Add(new EmptyGridRow() { Columns = col });
else
{
tableStatus = false;
ClientScript.RegisterStartupScript(this.GetType(), "error", "<script>alert('" + errorMsg + "');</script>");
}
}
if (tableStatus == true)
{
//Binding the EmptyTemplate to our GridView
EmptyGridTemplate objTemplate = new EmptyGridTemplate(ListItemType.Header, lstRows, _pageName);
GridView1.EmptyDataTemplate = objTemplate;
GridView1.DataBind();
}
}
}
}
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.
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:
I hope you all liked the article.