Tuesday, 29 May 2012

GRIDVIEW ZOOM IMAGE


When you have images in your GridView, you would most likely show them as thumbnails so as to not distort the whole layout. However user would want to look at the full image by clicking on the image or just hovering his mouse over it. In today’s applications, this is a basic requirement and there are just so many third party controls or plugins which would support this functionality. I am going do this conventional way using javascript way in this article.  On top of it, I am also going to explain how to get images from database using HttpHandlers.
Example:
I am using Adventure Works as datasource. We fetch handful of products and bind them to the grid. When page is initially loaded, we retrieve products fromProduction.Product table and bind them to the grid. We display some product attributes such as Product ID, Product Number, Product Name, List Price and product’s thumbnail. When user hover his mouse on the page, we fetch the full-size image from the database and display it to the user.
Open web.config and add following entry under connection strings element
<add name="Sql" connectionString="Data Source={local};
     Initial CatalogAdventureWorkd;User=testuser;Password=testuser;"
     providerName="System.Data.SqlClient"/>
I am using SQLDataSource to load the products from database. The ConnectionString property of the SqlDataSource control specifies how to connect to the database. This property can be a hard-coded connection string or can point to a connection string in a Web.config file as shown in the code given above. TheSelectCommand property specifies the SQL statement to execute to retrieve the data.
<asp:SqlDataSource ID="sqlDSProducts" runat="server"
    ConnectionString="<%$ ConnectionStrings:Sql %>"
    SelectCommand="Select top 10 * from Production.Product"/>
We are interested in ProductID, ProductName, ProductNumber and LisPrice attributes of the product. I have added Bound/Template Columns to the GridView to render these attributes. As you would notice, we are using Image web control to render product’s thumbnail. We are setting the URL to our HTTP Handler and passing ProductID in the query string to the handler. I would explain the implementation of the Http Handler later. We are calling javascript function fnZoomImageto zoom the image when user moves his mouse over the image and invoking HideImage when he moves his mouseout. I would explain these javascript functions later in the article.  In order to bind the SQLDataSource created above to the grid, set the “DataSourceID” property of the GridView to “sqlDSProducts” (ID property value of SQLDataSource).
<asp:gridview id="gvProducts"
  autogeneratecolumns="False"
  emptydatatext="No data available."
  runat="server" DataKeyNames="ProductID"
  CssClass="mGrid" >
<Columns>
    <asp:BoundField DataField="ProductID" HeaderText="Product ID"/>
    <asp:BoundField DataField="Name" HeaderText="Product Name" />
    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" />
    <asp:BoundField HeaderText="Price"
            DataField="ListPrice"
            DataFormatString="{0:c}">
        <ItemStyle HorizontalAlign="Right"></ItemStyle>
    </asp:BoundField>
    <asp:TemplateField>
        <ItemTemplate>
            <asp:Image ID="imgPhoto" runat="server"
                onmouseover "fnZoomImage(this.src);"
                onmouseout "HideImage();"
                ImageUrl = '<%#"ImageHttpHandler.ashx?
                   ProductID="+Eval("ProductID")+"&ViewMode=Thumbnail"%>' />
        </ItemTemplate>
    </asp:TemplateField>
</Columns>
</asp:gridview>
I have created a simple DIV element and added a image control to it. We will embed the fullsize image into this control in the javascript function.  I have applied custom style to this DIV to align this to center and other basic formatting as border etc.
<div id="divImage" class="zoomClass">
    <table style="height: 100%; width: 100%">
        <tr>
            <td valign="middle" align="center">
                <img id="imgZoom" runat="server" style="display: none;"/>
            </td>
        </tr>
    </table>
</div>
 
.zoomClass
{
    display: none;
    position: fixed;
    top: 20px;
    left: 0px;
    background-color: #FFFFFF;
    height: 500px;
    width: 600px;
    padding: 3px;
    border: solid 1px #525252;
}
HTTP handlers are the .NET components that implement System.Web.IHttpHandler interface. They can act as a target for the incoming HTTP requests and can be called directly by using their file name in the URL. When a request is made to the web server for an ASP.NET resource (.aspx, .asmx, ashx etc.), the worker process of the ASP.NET creates the right HttpHandler for the request which responds to the request.
If you look at the design, we are setting the URL of the image to ImageHttpHandler.ashx?ProductID=1&ViewMode=Thumbnail. The resource request will be routed to ProcessContext method of ImageHttpHandler. The ProcessRequest method is responsible for processing individual HTTP requests. In this method, you write the code that produces the output for the handler.
HTTP handlers have access to the application context. This includes the requesting user’s identity (if known), application state, and session information. In our example we are sending two values to the handler in the query string i.e. ProductID and ViewMode. ProductID would be used in the SQL query to get the photo name & binary content. ViewMode is used to figure out whether to get Thumbnail or FullSize image.
public class ImageHttpHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
    int productID =
               Convert.ToInt32(context.Request.QueryString["ProductID"]);
    string viewMode =
                Convert.ToString(context.Request.QueryString["ViewMode"]);
    if (productID > 0)
    {
        context.Response.BinaryWrite(
                     RetrieveProductImage(productID,viewMode));
        context.Response.End();
    }
}
private Byte[] RetrieveProductImage(int ProductID, string ViewMode)
{
    //fetch the connection string from web.config
    string connString =
                  ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
 
    //SQL statement to fetch thumbnail photo
    string sql = @"Select {0},{1}
from Production.ProductPhoto PP
inner join Production.ProductProductPhoto PPP on PP.ProductPhotoID = PPP.ProductPhotoID
where ProductID = {2}";
 
    if (ViewMode.Equals("Full"))
        sql = String.Format(sql,"LargePhoto",
                   "LargePhotoFileName", ProductID);
    else
        sql = String.Format(sql, "ThumbNailPhoto",
                   "ThumbnailPhotoFileName", ProductID);
 
    DataTable dtProductsPhoto = new DataTable();
    //Open SQL Connection
    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();
        //Initialize command object
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
            //Fill the result set
            adapter.Fill(dtProductsPhoto);
        }
    }
    return (Byte[])dtProductsPhoto.Rows[0][0];
}
public bool IsReusable
{
    get{
        return false;
    }
}
}
We must now register the handler in Web.config file.  The verb part is just what you want it to respond to (GET, POST, etc.). Path is the file or file extension you want it to respond to and Type is – ClassName, Assembly. The way you register to the handler depends upon the IIS version you are running and its mode (classic or Integrated mode).
<httpHandlers>
  <add verb="*" path="*ImageHttpHandler.ashx"
                      type="GridView.ImageHttpHandler,GridView" />
</httpHandlers>
When the user hovers over the image, fnZoomImage function is called. In this function we have access to the imageUrl i.e. ImageHttpHandler.ashx?ProductID=1&ViewMode=Thumbnail. This productiD and ViewMode values are used by the httphandler to figure out whether to return thumbnail image or full-size image. Since we are interested in FULLSIZE image, we change the ViewMode to “Full” and will set the url of this image control. This resource request will be routed to ImageHttpHandler which will return FULLSIZE image. Finally we simply make the DIV element visible.
function fnZoomImage(imageUrl) {
     var imgDiv = document.getElementById("divImage");
     var imgZoom = document.getElementById("imgZoom");
     imgZoom.src = imageUrl.replace("Thumbnail""Full");
     var width = document.body.clientWidth;
     imgDiv.style.left = (width - 650) / 2 + "px";
     imgDiv.style.display = "block";
     imgZoom.style.display = "block";
     return false;
 }
When user moves his mouse out, HideImage function is called where we hide the DIV element.
function HideImage() {
     var imgDiv = document.getElementById("divImage");
     var imgZoom = document.getElementById("imgZoom");
     imgDiv.style.display = "none";
     imgZoom.style.display = "none";
 }
When you hover over any thumbnail, you would see a full image.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.