Customize DataGrid Behavior

If you can imagine it, you can do it.

ask the PRO

LANGUAGES: C#

TECHNOLOGIES: DataGrid

 

Customize DataGrid Behavior

If you can imagine it, you can do it.

 

By Jeff Prosise

 

I'm binding a DataGrid to a set of records containing a Boolean (bit) column. Rather than accept the DataGrid's default behavior, which is to render Boolean values using the words True and False, I'd prefer to render Booleans with the words Yes and No. Better yet, I'd like to render Boolean values using check marks, with an empty cell indicating that the corresponding value is false. Is this possible?

 

With ASP.NET's DataGrid control, practically anything is possible - as long as you can express in HTML what you want the DataGrid to display.

 

Let's start with simply displaying Yes or No. The most straightforward way to render 1 as Yes and 0 as No is to use template columns, which are instances of System.Web.UI.TemplateColumn. You define a template column's contents using HTML templates - snippets of HTML that tell a control how to render the items it encounters during data binding. The page in Figure 1 uses a template column to render the Discontinued field of the SQL Server Northwind database's Products table using instances of Yes and No.

 

<%@ Import Namespace="System.Data.SqlClient" %>

  

    

      

        AutogenerateColumns="false" Width="100%"

        Font-Name="Verdana" Font-Size="8pt">

        

          

            DataField="ProductName" />

          

            ItemStyle-HorizontalAlign="center">

            

              <%# (bool) DataBinder.Eval

                 (Container.DataItem, "Discontinued") ?

                "Yes" : "No" %>

            

          

        

        

        

      

    

  

 

Figure 1. Template columns provide a handy and easy means for custom-rendering database fields. The DataGrid in this example renders Booleans as instances of Yes and No.

 

The data-binding expression (everything between <%# and %>) in the item template casts the current record's Discontinued field to a bool and outputs Yes if the resulting value is true, or No if the value is false. See the result in Figure 2.

 


Figure 2. One application for template columns is to render Boolean values as instances of Yes and No, as pictured in this DataGrid's right-most column.

 

Once you're comfortable with template columns, you can shape them into a variety of different forms. For example, replacing the item-template code in Figure 1 with the following code produces a column that displays check marks in cells whose values are true:

 

  <%# (bool) DataBinder.Eval (Container.DataItem,

    "Discontinued") ? "" : "" %>

 

See how it works? If the Discontinued field holds a Boolean True, the data-binding expression writes an tag into the HTML output. Otherwise, the expression writes nothing and produces a blank cell. Figure 3 shows the resulting DataGrid.

 


Figure 3. A simple change to the template column renders Boolean database fields using check marks.

 

Display Images From a Database

How do I create a DataGrid column that displays images obtained from a database?

 

This is a commonly asked question regarding DataGrids, and it's easy enough to answer by combining what you already know about template columns with a little knowledge of HTTP handlers.

 

The page in Figure 4 shows how to display database images in a DataGrid using the Northwind database's Employees table.

 

<%@ Import Namespace="System.Data.SqlClient" %>

 

  

    

      

        AutogenerateColumns="false" Width="100%"

        Font-Name="Verdana" Font-Size="8pt">

        

          

            HeaderStyle-HorizontalAlign="center">

            

              

                

              

            

          

          

            DataField="LastName" />

          

            DataField="FirstName" />

          

            DataField="Title" />

        

        

        

      

    

  

 

Figure 4. To fetch images from a database and display them in a DataGrid, use a template column to output tags referencing HTTP handlers that query the database and return the images.

 

The Employees table contains a list of fictitious employees and includes employee photos in a field named Photo. The DataGrid in the sample page uses a template column to output an tag whose src attribute references a file named ImageGrabber.ashx. A typical tag output by the template column looks like this:

 

 

ImageGrabber.ashx, shown in Figure 5, is an HTTP handler. When invoked, its ProcessRequest method grabs the employee ID from the query string and uses it to perform a query of its own. That query retrieves the Photo field of the corresponding record, creates a bitmap from it, and streams the bitmap back to the client as a JPEG.

 

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

 

using System;

using System.Web;

using System.Drawing;

using System.Drawing.Imaging;

using System.Data.SqlClient;

using System.IO;

 

public class ImageGrabber : IHttpHandler

{

    public void ProcessRequest (HttpContext context)

    {

        string id = (string) context.Request["id"];

 

        if (id != null) {

            MemoryStream stream = new MemoryStream ();

            SqlConnection connection = new SqlConnection

             ("server=localhost;database=northwind;uid=sa");

            Bitmap bitmap = null;

            Image image = null;

 

            try {

                connection.Open ();

                SqlCommand cmd = new SqlCommand

                     ("SELECT Photo FROM Employees WHERE " +

                    "EmployeeID='" + id + "'", connection);

                byte[] blob = (byte[]) cmd.ExecuteScalar ();

 

                stream.Write (blob, 78, blob.Length - 78);

                bitmap = new Bitmap (stream);

 

                int width = 48;

                int height = (int) (width *

                     ((double) bitmap.Height /

                     (double) bitmap.Width));

                 image = bitmap.GetThumbnailImage (width,

                    height, null, IntPtr.Zero);

 

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

                image.Save (context.Response.OutputStream,

                    ImageFormat.Jpeg);

            }

            finally {

                if (image != null)

                    image.Dispose ();

                if (bitmap != null)

                    bitmap.Dispose ();

                stream.Close ();

                connection.Close ();

            }

        }

    }

 

    public bool IsReusable

    {

        get { return true; }

    }

}

Figure 5. This custom HTTP handler extracts images from Microsoft's Northwind database. Images are identified by employee IDs passed in query strings.

 

For good measure, ProcessRequest also uses the Framework Class Library's handy Image.GetThumbnailImage method to shrink the bitmap to a width of 48 pixels while preserving its aspect ratio. The result is shown in Figure 6.

 


Figure 6. Combine template columns with custom HTTP handlers, and what do you get? Picture DataGrids!

 

You can use a similar technique to create DataGrids that display images from other databases. The basic idea is to use a template column to output an tag referencing an HTTP handler and include information uniquely identifying the record containing the image in a query string. Then, the HTTP handler uses ADO.NET to fetch the image bits and GDI+ to build the image. Significantly, the image is built in memory on the server and is streamed back to the client in the HTTP response. At the appropriate time, the garbage collector frees up the memory.

 

The subject of HTTP handlers - and the use of custom HTTP handlers to extend ASP.NET - is a rich one that deserves further treatment. Stay tuned for more on HTTP handlers in a future installment of this column.

 

The sample code in this article is available for download.

 

Jeff Prosise is the author of several books, including Programming Microsoft .NET (Microsoft Press). He's also a co-founder of Wintellect (http://www.wintellect.com), a software-consulting and education firm that specializes in .NET. Have a question for this column? Submit queries to [email protected].

 

Tell us what you think! Please send any comments about this article to [email protected]. Please include the article title and author.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish