Thursday, October 23, 2008

GridView Tips and Tricks using ASP.NET – Part III ( Fron dotnetcurry)

GridView Tips and Tricks using ASP.NET – Part III


The GridView control is quiet a handy control and is the most commonly used control when building an ASP.NET site. The more you work with it, the more you realize how powerful it can be while presenting data.

Moving ahead with our GridView Tips and tricks series, I have added some more tips in this article. The previous two articles on the Tips and Tricks are mentioned below:



For this article, we would be using the following template to populate the GridView.

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>GridView Tips and Tricks Part 2</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CategoryID"

DataSourceID="SqlDataSource1" ShowFooter="true" AllowPaging="True" AllowSorting="True"

PageSize="5" OnRowDataBound="GridView1_RowDataBound">

<Columns>

<asp:TemplateField HeaderText="CategoryID" InsertVisible="False" SortExpression="CategoryID">

<ItemTemplate>

<asp:Label ID="lblCategoryID" runat="server" Text='<%# Bind("CategoryID") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

<asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">

<EditItemTemplate>

<asp:TextBox ID="txtCategoryName" runat="server" Text='<%# Bind("CategoryName") %>'></asp:TextBox>

</EditItemTemplate>

<ItemTemplate>

<asp:Label ID="lblCategoryName" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

<asp:TemplateField HeaderText="Description" SortExpression="Description">

<EditItemTemplate>

<asp:TextBox ID="txtDesc" runat="server" Text='<%# Bind("Description") %>'></asp:TextBox>

</EditItemTemplate>

<ItemTemplate>

<asp:Label ID="lblDesc" runat="server" Text='<%# Bind("Description") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

</Columns>

</asp:GridView>

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="Data Source=SUPROTIM;Initial Catalog=Northwind;Integrated Security=True"

ProviderName="System.Data.SqlClient" SelectCommand="SELECT [CategoryID], [CategoryName], [Description] FROM [Categories]"

UpdateCommand="UPDATE [Categories] SET [CategoryName] = @CategoryName, [Description] = @Description WHERE [CategoryID] = @CategoryID"/>

</div>

</form>

</body>

</html>

The web.config holding the connection will look similar to the following:

<configuration>

<appSettings/>

<connectionStrings>

<add name="NorthwindConnectionString" connectionString="Data Source =(local);Integrated Security = SSPI; Initial Catalog=Northwind;"/>

</connectionStrings>

...

</configuration>


Tip 1: Change the color of a GridView Row based on some condition

C#

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)

{

if (e.Row.DataItem != null)

{

DataRowView drv = (DataRowView)e.Row.DataItem;

string catName = Convert.ToString(drv["CategoryName"]);

if (catName.Trim() == "Confections")

e.Row.BackColor = System.Drawing.Color.LightBlue;

}

}

VB.NET

Protected Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

If Not e.Row.DataItem Is Nothing Then

Dim drv As DataRowView = CType(e.Row.DataItem, DataRowView)

Dim catName As String = Convert.ToString(drv("CategoryName"))

If catName.Trim() = "Confections" Then

e.Row.BackColor = System.Drawing.Color.LightBlue

End If

End If

End Sub

Tip 2: How to create an Image Command Field Column and add to the GridView at runtime

C#

if (!Page.IsPostBack)

{

CommandField cmdField = new CommandField();

cmdField.ButtonType = ButtonType.Image;

cmdField.SelectImageUrl = "~/Images/Home_Np1.GIF";

cmdField.ShowSelectButton = true;

cmdField.HeaderText = "Select";

GridView1.Columns.Add(cmdField);

GridView1.DataBind();

}

VB.NET

If (Not Page.IsPostBack) Then

Dim cmdField As CommandField = New CommandField()

cmdField.ButtonType = ButtonType.Image

cmdField.SelectImageUrl = "~/Images/Home_Np1.GIF"

cmdField.ShowSelectButton = True

cmdField.HeaderText = "Select"

GridView1.Columns.Add(cmdField)

GridView1.DataBind()

End If

Tip 3: How to display images in the GridView from Filesystem based on an existing Column

Let us imagine that you have a folder ‘Images’ where you have stored images for each category. Eg: 1.GIF, 2.GIF, 3.GIF and so on. Now you want to display a different image based on each CategoryID. So for CategoryID = 1, the image is 1.GIF; for CategoryID=2, the image is 2.GIF and so on.

<asp:TemplateField>

<ItemTemplate>

<asp:Image runat="server" ImageUrl='<%# "~/Images/"+ Eval("CategoryID") + ".GIF" %>' >

</asp:Image>

</ItemTemplate>

</asp:TemplateField>

Tip 4: How to Retrieve Images from the database and display it in a GridView

I will assume that we have a image column called CatImg in the Categories table.

The first step would be to create an ImageHandler. In such scenarios such as the gridview, usually prefer to go in for a handler when I have to return binary data directly from the database. It gives more control on the resource returned. Moreover it is a preferred solution when you have to set the image programmatically.

To add a handler, right click project > Add New Item > Generic Handler > ShowImage.ashx. The code shown below, uses the Request.QueryString[“id”] to retrieve the CategoryID from it. The ID is then passed to the ‘ShowCatImage()’ method where the image is fetched from the database and returned in a MemoryStream object. We then read the stream into a byte array. Using the OutputStream.Write(), we write the sequence of bytes to the current stream and you get to see your image.

C#

<%@ WebHandler Language="C#" Class="ShowImage" %>


using System;

using System.Configuration;

using System.Web;

using System.IO;

using System.Data;

using System.Data.SqlClient;


public class ShowImage : IHttpHandler

{

public void ProcessRequest(HttpContext context)

{

Int32 catid;

if (context.Request.QueryString["id"] != null)

catid = Convert.ToInt32(context.Request.QueryString["id"]);

else

throw new ArgumentException("No parameter specified");


context.Response.ContentType = "image/jpeg";

Stream strm = ShowCatImage(catid);

byte[] buffer = new byte[4096];

int byteSeq = strm.Read(buffer, 0, 4096);


while (byteSeq > 0)

{

context.Response.OutputStream.Write(buffer, 0, byteSeq);

byteSeq = strm.Read(buffer, 0, 4096);

}

//context.Response.BinaryWrite(buffer);

}


public Stream ShowCatImage(int catid)

{

string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;

SqlConnection connection = new SqlConnection(conn);

string sql = "SELECT catImg FROM Categories WHERE CategoryID = @ID";

SqlCommand cmd = new SqlCommand(sql, connection);

cmd.CommandType = CommandType.Text;

cmd.Parameters.AddWithValue("@ID", catid);

connection.Open();

object img = cmd.ExecuteScalar();

try

{

return new MemoryStream((byte[])img);

}

catch

{

return null;

}

finally

{

connection.Close();

}

}


public bool IsReusable

{

get

{

return false;

}

}



}


VB.NET

<%@ WebHandler Language="vb" Class="ShowImage" %>


Imports System

Imports System.Configuration

Imports System.Web

Imports System.IO

Imports System.Data

Imports System.Data.SqlClient


Public Class ShowImage

Implements IHttpHandler

Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

Dim catid As Int32

If Not context.Request.QueryString("id") Is Nothing Then

catid = Convert.ToInt32(context.Request.QueryString("id"))

Else

Throw New ArgumentException("No parameter specified")

End If


context.Response.ContentType = "image/jpeg"

Dim strm As Stream = ShowCatImage(catid)

Dim buffer As Byte() = New Byte(4095){}

Dim byteSeq As Integer = strm.Read(buffer, 0, 4096)


Do While byteSeq > 0

context.Response.OutputStream.Write(buffer, 0, byteSeq)

byteSeq = strm.Read(buffer, 0, 4096)

Loop

'context.Response.BinaryWrite(buffer);

End Sub


Public Function ShowCatImage(ByVal catid As Integer) As Stream

Dim conn As String = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString

Dim connection As SqlConnection = New SqlConnection(conn)

Dim sql As String = "SELECT catImg FROM Categories WHERE CategoryID = @ID"

Dim cmd As SqlCommand = New SqlCommand(sql, connection)

cmd.CommandType = CommandType.Text

cmd.Parameters.AddWithValue("@ID", catid)

connection.Open()

Dim img As Object = cmd.ExecuteScalar()

Try

Return New MemoryStream(CType(img, Byte()))

Catch

Return Nothing

Finally

connection.Close()

End Try

End Function


Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable

Get

Return False

End Get

End Property



End Class


To access this image in the GridView based on the CategoryID, just add the following:

<asp:TemplateField>

<ItemTemplate>

<asp:Image runat="server" ImageUrl='<%# "ShowImage.ashx?id=" + Eval("CategoryID") %>' >

</asp:Image>

</ItemTemplate>

</asp:TemplateField>

Tip 5: How to programmatically enable/disable a control in the GridView when in the Edit Mode

If you want to quickly take a decision whether to enable or disable a control when the user edits the row, then use the Enabled attribute and set it to a method that returns a bool value:

<asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">

<EditItemTemplate>

<asp:TextBox ID="txtCategoryName" runat="server" Enabled='<%# EnableDisableTextBox() %>' Text='<%# Bind("CategoryName") %>'></asp:TextBox>

</EditItemTemplate>

<ItemTemplate>

<asp:Label ID="lblCategoryName" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

C#

protected bool EnableDisableTextBox()

{

if (1 == 1)

return false;

}

VB.NET

Protected Function EnableDisableTextBox() As Boolean

If 1 = 1 Then

Return False

End If

End Function

You can test this code by adding a CommandField to the GridView as shown below

<asp:CommandField ButtonType="Link" ShowEditButton="true" />

Tip 6: How to insert an Image in between Rows of a GridView using ASP.NET

Please check my article on the same over here


Tip 7: How to loop through all the rows in all the pages of a GridView

One simple way to loop through all the rows in all the pages of a GridView is to access its DataSource. In this example, we will loop through the SQLDataSource to retrieve all the rows in a GridView and access its cell value. You can modify the logic depending on the type of controls you have added to the GridView

C#

protected void Button1_Click(object sender, EventArgs e)

{

DataSourceSelectArguments dsaArgs = new DataSourceSelectArguments();

DataView view = (DataView)SqlDataSource1.Select(dsaArgs);

DataTable dt = view.ToTable();

for (int i = 0; i < dt.Rows.Count; i++)

{

for (int j = 0; j < dt.Columns.Count; j++)

{

string s = dt.Rows[i][j].ToString();

}

}

}

VB.NET

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)

Dim dsaArgs As DataSourceSelectArguments = New DataSourceSelectArguments()

Dim view As DataView = CType(SqlDataSource1.Select(dsaArgs), DataView)

Dim dt As DataTable = view.ToTable()

For i As Integer = 0 To dt.Rows.Count - 1

For j As Integer = 0 To dt.Columns.Count - 1

Dim s As String = dt.Rows(i)(j).ToString()

Next j

Next i

End Sub

Well that was a quick overview of some of the most frequently used features of the GridView control. I hope you liked the article and I thank you for viewing it.

GridView Tips and Tricks using ASP.NET - Part II (From dotnetcurry)

Some More GridView Tips and Tricks using ASP.NET - Part II


The GridView control is quiet a handy control and is the most commonly used control when building an ASP.NET site. The more you work with it, the more you realize how powerful it can be while presenting data.

In one of our previous articles GridView Tips and Tricks using ASP.NET 2.0, we discussed ten of the most frequently asked questions about the GridView control. This article adds ten more tips and tricks to our collection, related to the GridView control.

[Update: The 3rd part of the GridView Tips and Tricks can be found over here: GridView Tips and Tricks using ASP.NET - Part III ]

For this article, we would be using the following template to populate the GridView.

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>GridView Tips and Tricks Part 2</title>

</head>

<body>

<form id="form1" runat="server">

<div>

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CategoryID"

DataSourceID="SqlDataSource1" ShowFooter="true" AllowPaging="True" AllowSorting="True"

PageSize="5" OnRowDataBound="GridView1_RowDataBound">

<Columns>

<asp:TemplateField HeaderText="CategoryID" InsertVisible="False" SortExpression="CategoryID">

<ItemTemplate>

<asp:Label ID="lblCategoryID" runat="server" Text='<%# Bind("CategoryID") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

<asp:TemplateField HeaderText="CategoryName" SortExpression="CategoryName">

<EditItemTemplate>

<asp:TextBox ID="txtCategoryName" runat="server" Text='<%# Bind("CategoryName") %>'></asp:TextBox>

</EditItemTemplate>

<ItemTemplate>

<asp:Label ID="lblCategoryName" runat="server" Text='<%# Bind("CategoryName") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

<asp:TemplateField HeaderText="Description" SortExpression="Description">

<EditItemTemplate>

<asp:TextBox ID="txtDesc" runat="server" Text='<%# Bind("Description") %>'></asp:TextBox>

</EditItemTemplate>

<ItemTemplate>

<asp:Label ID="lblDesc" runat="server" Text='<%# Bind("Description") %>'></asp:Label>

</ItemTemplate>

</asp:TemplateField>

</Columns>

</asp:GridView>

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="Data Source=SUPROTIM;Initial Catalog=Northwind;Integrated Security=True"

ProviderName="System.Data.SqlClient" SelectCommand="SELECT [CategoryID], [CategoryName], [Description] FROM [Categories]"

UpdateCommand="UPDATE [Categories] SET [CategoryName] = @CategoryName, [Description] = @Description WHERE [CategoryID] = @CategoryID"/>

</div>

</form>

</body>

</html>

The web.config holding the connection will look similar to the following:

<configuration>

<appSettings/>

<connectionStrings>

<add name="NorthwindConnectionString" connectionString="Data Source =(local);Integrated Security = SSPI; Initial Catalog=Northwind;"/>

</connectionStrings>

...

</configuration>

Tip 1: Enable Disable Controls inside a GridView

There are at times when you have to disable controls on some rows, when a certain condition is satisfied. In this snippet, we will see how to disable editing for rows that have the CategoryName as ‘Confections’. Use the following code:

C#

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

{

if (e.Row.RowType == DataControlRowType.DataRow)

{

if (e.Row.DataItem != null)

{

Label lblControl = (Label)e.Row.Cells[2].FindControl("lblCategoryName");


if(lblControl.Text == "Confections")

{

e.Row.Cells[0].Enabled = false;

}

}

}

}

VB.NET

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

If e.Row.RowType = DataControlRowType.DataRow Then

If Not e.Row.DataItem Is Nothing Then

Dim lblControl As Label = CType(e.Row.Cells(2).FindControl("lblCategoryName"), Label)


If lblControl.Text = "Confections" Then

e.Row.Cells(0).Enabled = False

End If

End If

End If

End Sub


Tip 2: Adding Arrows for Sorting Columns in a GridView

When you are sorting the columns in a GridView, it would be a nice to have feature, to display arrows which depict either an ascending or descending sort as shown below. Create a folder called ‘images’ and add two small images called up.gif and down.gif:

C#

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

{

if (e.Row.RowType == DataControlRowType.Header)

{

foreach (TableCell cell in e.Row.Cells)

{

if (cell.HasControls())

{

LinkButton btnSort = (LinkButton)cell.Controls[0];

Image image = new Image();

if (btnSort.Text == GridView1.SortExpression)

{

if (GridView1.SortDirection == SortDirection.Ascending)

{

image.ImageUrl = "images/up.gif"; }

else

{

image.ImageUrl = "images/down.gif";

}

}

cell.Controls.Add(image);


}

}

VB.NET

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

If e.Row.RowType = DataControlRowType.Header Then

For Each cell As TableCell In e.Row.Cells

If cell.HasControls() Then

Dim btnSort As LinkButton = CType(cell.Controls(0), LinkButton)

Dim image As Image = New Image()

If btnSort.Text = GridView1.SortExpression Then

If GridView1.SortDirection = SortDirection.Ascending Then

image.ImageUrl = "images/up.gif"

Else

image.ImageUrl = "images/down.gif"

End If

End If

cell.Controls.Add(image)

End If

Next cell

Tip 3: How to Add a Row Number to the Gridview

There are a couple of ways to do this. However I will share a very handy tip that was shared by XIII in the asp.net forums.

Just add the following tags to your <columns> section of your GridView

<asp:TemplateField>

    <ItemTemplate>

        <%# Container.DataItemIndex + 1 %>

    </ItemTemplate>

</asp:TemplateField>

Tip 4: How to programmatically hide a column in the GridView

There are two conditions to be checked in the Page_Load to hide a columns in the GridView, let us say the 3rd column:

If ‘AutoGenerateColumns’ = True on the GridView

C#

GridView1.HeaderRow.Cells[2].Visible = false;

foreach (GridViewRow gvr in GridView1.Rows)

{

gvr.Cells[2].Visible = false;

}

VB.NET

GridView1.HeaderRow.Cells(2).Visible = False

For Each gvr As GridViewRow In GridView1.Rows

gvr.Cells(2).Visible = False

Next gvr

If ‘AutoGenerateColumns’ = False on the GridView

C#

GridView1.Columns[2].Visible = false;

VB.NET

GridView1.Columns(2).Visible = False

Tip 5: Handling Concurrency Issues in GridView

If you are using the SqlDataSource (or ObjectDataSource), you can use both the SqlDataSource.ConflictDetection and OldValuesParameterFormatString property to handle concurrency issues. These two properties together control how to perform updates and delete operations when the underlying data source changes, while the operation is being carried out. The original and modified versions of each column can be tracked using the two properties.

Read more about it over here.

Tip 6: How to transfer multiple values from GridView to a different page

Check my article over here:


Tip 7: Displaying Empty Data in a GridView

When there are no results returned from the GridView control’s data source, the short and simple way of displaying a message to the user, is to use the GridView’s EmptyDataText property.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CategoryID"

DataSourceID="SqlDataSource1" EmptyDataText="No data available"

ShowFooter="true" AllowPaging="True" AllowSorting="True"

PageSize="5" OnRowDataBound="GridView1_RowDataBound">

Note: You can also add style to the EmptyDataText by using the EmptyDataRowStyle property.

Tip 8: Displaying an Image in case of Empty Data in a GridView

As an alternative to using the EmptyDataText property, if you need to display an image or any HTML/ASP.NET control, you can use the EmptyDataTemplate. In this snippet below, we are using the image control in the <EmptyDataTemplate> to display an image.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CategoryID"

DataSourceID="SqlDataSource1" ShowFooter="true" AllowPaging="True" AllowSorting="True"

PageSize="5" OnRowDataBound="GridView1_RowDataBound">


<EmptyDataTemplate>

<asp:Image id="imgNoData"

ImageUrl="~/images/NoDataFound.jpg"

AlternateText="No data found"

runat="server"/>


</EmptyDataTemplate>

Tip 9: Highlight a Row in GridView without a PostBack

Check my article on the same over here:


Tip 10: How to Bind a List<> to a GridView

Let us see how to bind a List<> to a GridView. We assume that the ‘AutoGenerateColumns’ = True. We will create a class called Employees and bind it to the GridView with the help of a List<>.

Create a class called ‘Employees’

C#

public class Employee

{

private string enm;

private int ageofemp;

private string department;


public string EName

{

get

{

return enm;

}

set

{

enm = value;

}

}


public int Age

{

get

{

return ageofemp;

}

set

{

ageofemp = value;

}

}


public string Dept

{

get

{

return department;

}

set

{

department = value;

}

}


public Employee(string ename, int age, string dept)

{

this.enm = ename;

this.ageofemp = age;

this.department = dept;

}



}


VB.NET

Public Class Employee

Private enm As String

Private ageofemp As Integer

Private department As String


Public Property EName() As String

Get

Return enm

End Get

Set(ByVal value As String)

enm = value

End Set

End Property


Public Property Age() As Integer

Get

Return ageofemp

End Get

Set(ByVal value As Integer)

ageofemp = value

End Set

End Property


Public Property Dept() As String

Get

Return department

End Get

Set(ByVal value As String)

department = value

End Set

End Property


Public Sub New(ByVal ename As String, ByVal age As Integer, ByVal dept As String)

Me.enm = ename

Me.ageofemp = age

Me.department = dept

End Sub



End Class


Bind the ‘Employee’ data to the GridView using a List<>

C#

protected void Page_Load(object sender, EventArgs e)

{

System.Collections.Generic.List<Employee> emp = new System.Collections.Generic.List<Employee>();

emp.Add(new Employee("Jack", 22, "Marketing"));

emp.Add(new Employee("Anna", 28, "Advertising"));

emp.Add(new Employee("Linra", 23, "Advertising"));

emp.Add(new Employee("Jacob", 44, "Production"));

emp.Add(new Employee("Zinger", 28, "PPC"));


GridView1.DataSource = emp;

GridView1.DataBind();



}

VB.NET

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

Dim emp As System.Collections.Generic.List(Of Employee) = New System.Collections.Generic.List(Of Employee)()

emp.Add(New Employee("Jack", 22, "Marketing"))

emp.Add(New Employee("Anna", 28, "Advertising"))

emp.Add(New Employee("Linra", 23, "Advertising"))

emp.Add(New Employee("Jacob", 44, "Production"))

emp.Add(New Employee("Zinger", 28, "PPC"))


GridView1.DataSource = emp

GridView1.DataBind()



End Sub


Well that was a quick overview of some of the most frequently used features of the GridView control. I hope you liked the article and I thank you for viewing it.