Table of Contents
While answering questions on the Question and Answer Forums[^],
we noticed a certain pattern to the questions being asked very
frequently. Rather than trying to answer each question on an ad-hoc and
individual basis, we decided to club together a set of commonly asked questions into an
article. Everytime we notice a similar pattern-based question being asked,
we will now provide a link to this article, instead of providing
different answers for each question. This will help us to answer better
and people can have a look at other alternative solutions as well.
Let's start with ASP.NET GridView, which is an extremely flexible
data control in ASP.NET. It was observed that a number of questions
pertaining to the ASP.Net GridView are asked daily.
There will be a question on exporting the
GridView to Excel almost daily. Questions on GridView Template field,
Hiding specific values from a Cell, Changes Cell Values at run time are
very common as well.
Many other such patterns can be found if some time is spent in the Q&A forums.
We hope to keep this article updated by continuously adding more commonly asked questions to it.
Yes. You can. Though this is not a very common situation when you are enabling the AutoGenerateColumns="true"
and define custom columns. GridView creates a columns for each field when AutoGenerateColumns=true
. We set AutoGenerateColumns=false
, when we need few specific fields from the data source and define the cutom columns section with different types of columns.
So what will happen, if we set AutoGenerateColumns
to true and add "Columns" section to define columns? GridView will generated columns for each and every field, but before these auto generated columns, it will add the columns that you define explicitly.
GridView allows several types of columns to bind data that can be define explicitly. One of the most common column type is "BoundField
". Apart from bound field, GridView supports different types of Columns which includes ButtonField
, ImageField
, HyperLinkField
, TemplateField
etc. Let's have a quick look on how we can use BoundField to define gridview columns explicitly.
BoundField has a properties called "DataField". The DataField needs to associate with any of the data objects of the GridView DataSource.
This type column binding provides you enough opportunity to customize the columns and headers.
Another frequently asked question is how do we format a cell value? GridView BoundField
columns provides a property "DataFormatString" which you can use to format data. DataFormatString
take similar arguments like String.Format
, where it has one placeholder and another format indicator.
Here is a quick example of Date Formatting
This is also very useful when we need formatting for a Currency field. You can find list of all formatting string over here.
GridView TemplateField
allows us to specify custom controls, multiple fields and Html using a custom template. TemplateField
allows us to define a completely customized template for GridView Column. We can bind the data with in template control using binding expression. ASP.NET provides number of ways to take control over the template control.
Let's consider you have following design in a gridview
You now want to access the value of this label from code behind, where you want to update the text or you want to do some additional operation based on the value of label or other value. In the code snippet below we have shown that if the name is start with "A" it won't be displayed.
protected void myGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Customer cust = e.Row.DataItem as Customer;
if (!cust.ShowURL)
{
Label lableName = e.Row.FindControl("Label1") as Label;
if (lableName.Text.StartsWith("A"))
{
lableName.Visible = false;
}
}
}
}
So, for any situation, if you want to access the controls that are inside Template Fields, first check if the row is a "DataRow", then your GridViewRow.FindControl
method to get the control. Once you have the control of the same type you can do all additional operations.
If you want to hide any fields or control based on some conditional value, you can either do it from code behind or your can take help of a bind expression.
If you are following the approach of code behind, first of all, if need to find the control value during RowDataBound
of the Gridview. Once your have control, you can set the visibility of the control based on the condition that you want to apply.
The example below shows hiding a linkbutton based on some condition.
protected void myGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Customer cust = e.Row.DataItem as Customer;
if (!cust.ShowURL)
{
LinkButton lnkWebURL = e.Row.FindControl("lnk") as LinkButton;
if (lnkWebURL != null)
{
lnkWebURL.Visible = false;
}
}
}
}
Well, you can achieve the same thing in a smart way by just using Binding Expression. We can use Conditional Expression with in GridView Bind expression. So whatever you wrote in code behind can be replaced by just
This will first evaluate the value of "ShowURL" and then set the Visible property of GridView.
This question was recently asked in Q&A Forums, I answered and put a detailed blog post with an explanation at Dynamically set control visibility inside ItemTemplate’s of GridView using Bind Expression.
When we bind some data source with a GridView which contains some fields with NULL value, ASP.NET renders them as blank. But most of the time, we need to show a custom messages or images instated of null value. You can take help of RowDataBound
method for this and override the null value. Instead of doing that, its better to make use of "NullDisplayText" properties to replace the null value.
This will replace all the null values with plain text "No Data"
Once we mentioned NullDisplayText=”No Data”
, every field for that Bound Field which contains a NULL
value will be replace by “No Data” .
We can even customize the Text with HTML Formatting as shown below
The output will be as below
Original Source : Displaying Custom Messages / Images with NULL Value in ASP.NET GridView
If you are binding some data source in grid view which is having a field type of Boolean
, then the Grid View renders it as a “Checkbox” . But sometime we may required to display either Yes/ No or “1/0” instead of Checked/ Unchecked Text Box.
You can simple update the cell value on RowDataBind and change the default value as required.
protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Student s = (Student)e.Row.DataItem;
if (s.Status == true)
{
e.Row.Cells[2].Text = "1";
}
else
{
e.Row.Cells[2].Text = "0";
}
}
}
You can find the complete tips over here How to Display “Yes” or “No” Instead of Checkbox while binding Boolean value with GridView?
While working with GridView in ASP.NET, most of the times we use a HyperlinkField
column to navigate from one page to different page with some value as argument. In this blog post, I have explained how can we pass multiple parameter with HyperLinkField in GridView.
To implement this feature you need to know about DataNavigationUrlField
and DataNavigateUrlFormatString
properties of HyperLinkField
. Let’s assume that you have a gridview as given below and you have already bind the Datasource
from code behind.
<asp:gridview id="GrdEmp">
<columns runat="server" autogeneratecolumns="False" cellpadding="4">
<asp:boundfield datafield="ID" headertext="ID">
<asp:boundfield datafield="Name" headertext="Name">
<asp:boundfield datafield="ParentID" headertext="Base ID">
Let’s first consider the case of passing single parameter. The first thing that you need to do, is, to add a GridView “HyperLinkField
“ column. After that you need to set the DataNavigationUrlField
and DataNavigateUrlFormatString
properties for the same . In DataNavigationUrlField
you have to mention the name of the DataField which you want to bind as querystring. In DataNavigateUrlFormatString
you have to give the formatted URL String for the Navigation. The concept is same here as like FormatString the only difference is the data is coming from DataNavigationUrlField
.
<asp:hyperlinkfield text="Details" datanavigateurlfields="ID" datanavigateurlformatstring="/Details.aspx?EmpId={0}">
In the above example, I have passed an ID as a DataNavingationUrlField
. So asthe Gridview Binds, for each row corresponding ID will be bind as url string with Employee ID. The code snippet for the for the HTML View is right below.
<a href="http://www.codeproject.com/Default.aspx?EmpID=123">Details</a>
To add multiple parameters you need to specify multiple DataField with comma(,) separated with in DataNavigateURLFields
and also need to provide the DataNavigateURLFormatString
with proper number of argument.
asp:hyperlinkfield datanavigateurlformatstring="/Details.aspx?EmpId={0}&ParentID={1}" datanavigateurlfields="ID,ParentID" text="Details">
This is the HTML output for multiple parameter HyperLinkField.
<a href="http://www.codeproject.com/Default.aspx?EmpID=123&ParentID=765">Details</a>
So, to summarize the post, you can use Comma separated DataNavigateURLFields
to pass multiple DataField as an parameter with HyperlinkField
in GridView. Also you need to use proper formatted URL with DataaNavigateURLFormatString
.
Original Source : How to pass multiple values using GridView HyperLinkField ?
DataNavigationUrlField
uses only those fields as parameter which are part of GridView DataSource
. Now the problem comes when you want to pass some other variables as parameters which are not part of the DataSource
. As shown in the image below, we are passing EmpID and ParentId as arguments and these two field are the data members of GridView DataSource
.
Now say, you want to pass ChildID for that particular record along with ParentID
and EmpID
and you want that the hyperlink URL should be like “Default.aspx?EmpID=1&ParentID=P1&ChildID=C1
”where ChildID is not part of datasource.
You can achieve this by writing code in code behind for the particular GridView
. There are two events where you can overwrite the navigation URL of that hyperlink field. You can use Gridview_RowDataBound
or Gridview_PreRender
for the same.
Let’s start with Gridview_RowDataBound
. The RowDataBound
event of GridView
is raised when a data row is bound to data. So for each and every row RowDataBound event is raised to bind with actual data from the data source. On the RowDataBound event, you can check for the particular Cell control and can append the NavigateURL
. Below is the code snippet for the same:
protected void grdStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink hyperlink = (HyperLink)e.Row.Cells[0].Controls[0];
hyperlink.NavigateUrl += "&ChildID=" + this.ExternalValue;
}
}
And you can do the same thing in Gridview_PreRender
event in a similar way. As per the ASP.NET page life cycle, Pre_Render
for control is raised just before save view state and Render
event. This is the last event where you can customize your control before saving the viewstate
data and rendering it. Below is the code snippet for the same:
protected void grdStudent_PreRender(object sender, EventArgs e)
{
foreach (GridViewRow row in grdStudent.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
HyperLink grdviewLink = (HyperLink)row.Cells[0].Controls[0];
grdviewLink.NavigateUrl += "&ChildID=" + this.externalValue;
}
}
}
If you want to know how it’s actually working, just set a breakpoint during databound, you will find NavigateURL
for that hyperlink field has already been set with the value that you have passed as DataNavigationUrlField
. And inside RowDataBound or Pre_Render, we are appending the same NavigateURL with an external parameter.


Below is the HTML snippet for the same HyperLinkField
.

You can use NavigateURL
properties for Hyperlinkfield
to set URL, but NavigateURL
will set the same URL for all the rows. So if you want a different URL for each and every row, you have to use DataNavigationUrlField
or you need to override the NavigateURL during RowDataBound or Pre_Render. And if you set both the properties (NavigateURL
and DataNavigationUrlField
) the DataNavigationUrlField property takes precedence.
Exporting a GridView to Microsoft Excel is one of the most common questions asked in the forum.
The approach to this is fairly simple. The GridView can be copied row by row into an html table. This table can be written to an html stream and there, we have the excel.
Let us look at some code. The UI is fairly simple with a GridView containing some data and an export to excel button. This is what the UI would look like.
The UI code is just two lines and for completion sakes is being shown here.
<asp:gridview runat="server" autogeneratecolumns="true" height="66px" width="543px" style="z-index: 118" id="GridView1">
<asp:button onclick="Button1_Click" text="Export to Excel" runat="server" id="Button1">
The main code is written in the button click event. We will use the HttpContext's
Response
object.
An excel header is added to the Response
object (with the corresponding MIME type).
A StringWriter
object is created first. A HtmlTextWriter
object is created from this StringWriter
.
An html Table
is then created and the GridView is copied row by row into this table. This table is then rendered into the HtmlTextWriter
object.
The StringWriter
object is then written into the Response
and the browser is able to parse the response as an Excel file (provided it recognises the Excel MIME type).
Here is the code
protected void Button1_Click(object sender, EventArgs e)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition",
string.Format("attachment;filename={0}.xls", "Exported"));
HttpContext.Current.Response.Charset = "";
HttpContext.Current.Response.ContentType = "application/ms-excel";
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
Table table = new Table();
foreach (GridViewRow row in GridView1.Rows)
{
table.Rows.Add(row);
}
table.RenderControl(htw);
HttpContext.Current.Response.Write(sw.ToString());
HttpContext.Current.Response.End();
}
}
}
http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html [^]
is a good link on exporting a GridView to Excel, and this is what was referred to while preparing this tip.
A common question (though not as common as export to Excel) is importing an Excel file into a GridView. For this example, we will use a FileUpload
control to choose an excel from a particular drive.
Note that FileUpload
does not return the full file path to the server due to security reasons. The UI and its code look like this.
An import button is provided to do the actual import to the GridView. Binding is used to allow the GridView to bind to imported data.
The code behind on the Import button's Click
event is below.
protected void Import_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
String strConn = @"Provider = Microsoft.ACE.OLEDB.12.0;" + @"Data Source=C:\" + MyFile.FileName + @";Extended Properties='Excel 12.0;HDR=Yes;'";
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn);
da.Fill(ds);
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
Some lines of the above code require an explanation. In this example, the Jet engine is used to read an Excel file as the database.
The connection string's provider points to the OLEDB.12.0 version (rather than the 4.0 one) because Excel 2007 is being used. Thus the Extended Properties section is different as well.
HDR is nothing but an attribute that suggests that the first row in the Excel is to be used as a header (when set to YES). The entire connection string would be different when connecting to Excel 2003 or older.
A DataSet
is filled using a DataAdapter
and the first table is assigned to the GridView. That's all there is to it.
Another aproach to implement 'Import to Excel' would have been to use Excel Interop. This approach is not discussed here.
Adding a Dropdown in a GridView is a fairly common question as well.
Lets first have a look at the aspx
code. In order to define a dropdown, we will need to add ItemTemplates
to the code. The first two columns, Name and Age, will be simple DataBinders.
The third ItemTemplate
will contain a DropDownList
. Remember, AutoGenerateColumns
has been set to false. Fairly simple till here.
<columns>
<asp:templatefield headertext="Name">
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem, "Name")>
</itemtemplate>
</asp:templatefield>
<asp:templatefield headertext="Age">
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem, "Age")>
</itemtemplate>
</asp:templatefield>
<asp:templatefield sortexpression="Occupation" headertext="Occupation">
<itemtemplate>
<asp:dropdownlist id="DropDownList1" runat="server">
</itemtemplate>
</asp:templatefield>
</columns>
This is the UI the user sees on their screen.
The GridView
is populated using a DataTable
. This is fairly easy as well.
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
dt.Columns.Add("Occupation");
DataRow dr = dt.NewRow();
dr["Name"] = "Chris Harris";
dr["Age"] = "40";
dr["Occupation"] = "Doctor";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Sean Williams";
dr["Age"] = "39";
dr["Occupation"] = "Plumber";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Paul Newcombe";
dr["Age"] = "38";
dr["Occupation"] = "Lecturer";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
Now comes the slightly tricky part. In order to populate the GridView's DropDownList
, we need to run a loop through every row and find the DropDownList
within that row. This could be avoided if we had a static DataSource
.
Here though, we are using a DataSource
generated at rutime, we find the DropDownList and then bind it to the same dynamic DataSource's Occupation
column.
foreach (GridViewRow grdRow in GridView1.Rows)
{
DropDownList drdList = (DropDownList)(GridView1.Rows[grdRow.RowIndex].Cells[1].FindControl("DropDownList1"));
drdList.DataSource = dt;
drdList.DataValueField = "Occupation";
drdList.DataTextField = "Occupation";
drdList.DataBind();
}
That is it. We now have a DropDownList
in the GridView.
We can use similar code with minor enhancements and an EditTemplate
to display a DropDownList
in edit mode while allowing the user to see a label in normal mode.
If you have a GridView
with Multiple data key names like DataKeyNames="targetid,RequestID"
and now you want get their individual values, you have to do the following steps,
string targetID= gv.DataKeys[e.RowIndex].Values[0].ToString();
string requestID= gv.DataKeys[e.RowIndex].Values[1].ToString();
Also you can use,
gv.DataKeys[e.SelectedIndex].Values["targetid"];
gv.DataKeys[e.SelectedIndex].Values["RequestID"];
This question has been asked many times, and recently over here.
A very common question on the forums is about showing a DropDown in the GridView when the GridView is being edited.
This is fairly easy to do using an EditItemTemplate
.
The UI is farily simple. A GridView is shown with an Edit command in the first column and then three columns (Name, Age and Occupation) that would be holding the data.
Once the user clicks on the Edit button, a DropDownList is shown in the Occupation column.
Here is a snapshot of what the screen looks like when the Grid is in Edit mode.
Here is the UI code. Note the use of the Edit CommandField
and EditItemTemplate
. A normal ItemTemplate
is used for the scenario when the GridView is not in Edit mode.
<columns>
<asp:commandfield showeditbutton="True">
<asp:templatefield headertext="Name">
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem, "Name")>
</itemtemplate>
</asp:templatefield>
<asp:templatefield headertext="Age">
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem, "Age")>
</itemtemplate>
</asp:templatefield>
<asp:templatefield sortexpression="Occupation" headertext="Occupation">
<edititemtemplate>
<asp:dropdownlist id=""DropDownList1" runat="server">
</edititemtemplate>
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem,"Occupation")>
</itemtemplate>
</asp:templatefield>
</columns>
Lets move to the code behind. Two important points here.
The first one is that the binding to the DropDownList
must be done in the RowDataBound
event and not the RowEditing
event of the GridView
.
The RowEditingEvent
does not understand e.Row
. Also, the if condition in the RowDataBound
method is important, especially the check for the DataControlRowState
Edit.
This is because RowDataBound
is fired every time the GridView is bound and we only want to handle our scenario in the case when it is being edited.
The second important point (although not directly related to this sample), is the use of the RowEditing
event. This is what dislays the DropDownList
when the GridView enters Edit
mode.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow &&
(e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
DropDownList dl = (DropDownList)e.Row.FindControl("DropDownList1");
dl.DataSource = dt;
dl.DataValueField = "Occupation";
dl.DataTextField = "Occupation";
dl.DataBind();
}
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
GridView1.DataBind();
}
There you go. That is all there is to displaying a DropDownList
in Edit
mode in a GridView
.
A frequent questions on the forum is about displaying an image in a GridView.
An ImageField
is enough to do this. Here is what the web page and its code would look like (for a very simple scenario).
All we need to do is bind to the DataImageUrlField
field. As a note, an Images folder (containing the images) has been included in the project. This will be hosted on the server, along with the page itself.
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("PictureUrl");
DataRow dr = dt.NewRow();
dr["Name"] = "Hydrangeas.jpg";
dr["PictureUrl"] = ResolveUrl("~/Images/Hydrangeas.jpg");
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Lighthouse.jpg";
dr["PictureUrl"] = ResolveUrl("~/Images/Lighthouse.jpg");
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
The code behind is also fairly self explantory. A DataTable
acts as the source to the GridView. Note the use of the ResolveUrl
method to resolve the path of the image. That is all there is to get an image to display in a GridView.
Running a total for a numeric field inside a GridView is a topic that is often discussed. This can be easily be achieved by using a footer template. Take a look at the UI and code below.
Adding ShowFooter = "true"
is a necessity to show footers in a GridView. The FooterTemplate
takes care of the rest.
The codebehind makes use of the RowDataBound
method to do a sum.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
sum = sum + Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "Salary"));
}
if (e.Row.RowType == DataControlRowType.Footer)
{
Label obj = (Label)e.Row.FindControl("Sum");
obj.Text = Convert.ToString(sum);
}
}
The sum is calculated in this method and then finally assigned to the label. That is all there is to dispaying the sum in a footer.
Displaying nested gridview's is a fairly common question. Its fairly simple to do using an ItemTemplate
.
The UI and code is below. Not much to explain there - a couple of text fields and two grids (one inside the other).
This code is put into the Page_Load
event.
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
DataRow dr = dt.NewRow();
dr["Name"] = "Chris Harris";
dr["Age"] = "40";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Sean Williams";
dr["Age"] = "39";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Paul Newcombe";
dr["Age"] = "38";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
foreach (GridViewRow grdRow in GridView1.Rows)
{
GridView nestedView = (GridView)(GridView1.Rows[grdRow.RowIndex].Cells[2].FindControl("GridView2"));
nestedView.DataSource = dt;
nestedView.DataSource = LoadNestedData(grdRow.RowIndex);
nestedView.DataBind();
}
LoadNestedData
is the method that loads the nested grid. The code is not displayed here, but the code comments should give a general idea what this does.
The DataSource
to the nested gridview is set at runtime. Fairly simple.
Added 06/09/2011 : Get Individual DataKey value for multiple DataKeys
Added 06/09/2011 : Showing a DropDownList in a GridView in edit mode
Added 10/09/2011 : Displaying an Image in a GridView
Added 12/09/2011 : Importing an Excel file / Displaying a running total
Added 14/09/2011 : Displaying a Nested GridView
We are continuously looking for feedback from readers.
If there is any other topic a reader wants us to include, please feel free to post about it in the comments section below.
We will try to continue to update this article with more frequent questions from the Q&A and other forums.