This post is a continuation of Showing Tooltip on GridView column series. The previous post of this series can be find here. (But there is no dependency between each posts)
In this post, we are going to see how to show an image as tooltip when we hover the mouse on Grid View row where the image stored on the database field instead of url.
To understand how to store and retrieve image in the database, please look at this Post.
The actual functionality of the example taken in this post is shown below :
- Bind the Products data in the grid, with last column in each row contains an image.
- When the user hover the mouse on the last column image, show the image stored in the database for that product as tooltip.
- When no image stored for a product, show a default text/image for informing to the user “No image found”
- For good UI presentation, when the image retrieved from the database show a progress bar to let the user know something going on in background. (If the database connection is slow, user won’t feel bad showing the progress bar)
The GridView script will looks like this
<asp:GridView ID="grdViewProducts" runat="server" AllowPaging="True" AutoGenerateColumns="False" TabIndex="1" DataKeyNames="ProductID" Width="100%" ShowFooter="True" CellPadding="4" ForeColor="#333333" GridLines="None" > <RowStyle BackColor="#F7F6F3" ForeColor="#333333" /> <Columns> <asp:BoundField DataField="ProductID" HeaderText="Product ID" /> <asp:BoundField DataField="ProductName" HeaderText="Product Name" /> <asp:BoundField DataField="CompanyName" HeaderText="Supplier" /> <asp:BoundField DataField="CategoryName" HeaderText="Category" /> <asp:BoundField DataField="QuantityPerUnit" HeaderText="Quantity Per Unit" /> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" /> <asp:TemplateField HeaderText="Photo"> <ItemStyle Width="10%" HorizontalAlign="Center" /> <ItemTemplate> <img id="imgPhoto" src="Images/zoom_icon.jpg" onmouseover="ShowToolTipImage(event, this.alt)" onmouseout="HideTooTipImage()" onmousemove="MoveToolTipImage(event)" alt="<%# Eval("ProductID") %>,<%# Eval("IsImageAvailable") %> " width="20px" height="20px" title="<%# Eval("ProductName") %>" style="cursor:hand" /> </ItemTemplate> </asp:TemplateField> </Columns> <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" /> <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <EditRowStyle BackColor="#999999" /> <AlternatingRowStyle BackColor="White" ForeColor="#284775" /> </asp:GridView>To bind the data to the grid, BindGrid() method is used in code behind. The code would be
protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { BindGrid(); } } private void BindGrid() { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnection"].ConnectionString)) { SqlCommand command = new SqlCommand( "SELECT ProductID, ProductName, CompanyName, CategoryName, " + "QuantityPerUnit, UnitPrice, ProductImage FROM Products " + "JOIN Suppliers ON Products.SupplierID = Suppliers.SupplierID " + "JOIN Categories ON Products.CategoryID = Categories.CategoryID " + "Order by ProductID", connection); connection.Open(); SqlDataReader dr = command.ExecuteReader(CommandBehavior.CloseConnection); IList<ProductView> productViewList = new List<ProductView>(); while (dr.Read()) { ProductView productView = new ProductView(); productView.ProductID = dr["ProductID"].ToString(); productView.ProductName = dr["ProductName"].ToString(); productView.CompanyName = dr["CompanyName"].ToString(); productView.CategoryName = dr["CategoryName"].ToString(); productView.QuantityPerUnit = dr["QuantityPerUnit"].ToString(); productView.UnitPrice = Convert.ToDouble(dr["UnitPrice"].ToString()); productView.IsImageAvailable = ((dr["ProductImage"].ToString().Length > 0) ? true : false); productViewList.Add(productView); } grdViewProducts.DataSource = productViewList; grdViewProducts.DataBind(); } }The ProductView entity class
public class ProductView { public string ProductID { get; set; } public string ProductName { get; set; } public string CompanyName { get; set; } public string CategoryName { get; set; } public string QuantityPerUnit { get; set; } public double UnitPrice { get; set; } public bool IsImageAvailable { get; set; } }To get the image from the database there are two ways are available
- Generic Handler (extension .ashx)
- Web Page (extension .aspx)
The ProcessRequest() event on GenericHandler looks like:
System.Threading.Thread.Sleep(1000); using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnection"].ConnectionString)) { SqlCommand command = new SqlCommand( "select ProductImage from Products where ProductID = '" + context.Request.QueryString["ProductID"] + "'", connection); connection.Open(); SqlDataReader dr = command.ExecuteReader(CommandBehavior.CloseConnection); while (dr.Read()) { if (dr["ProductImage"].ToString().Length > 0) { context.Response.BinaryWrite((byte[])dr["ProductImage"]); } } }We are getting the product image from the query and converting as Byte[] stream and writing to the response.
The Javascript is follows :
// Declare General Variables var sTooTipId = 'divTooTip'; var sToolTipPlacement = "Left"; // Right, Left // For Hiding tool tip function HideTooTipImage() { // Get the Div element which was created dynamically on ShowToolTipImage function var divTip = document.getElementById(sTooTipId); if (divTip) { while (divTip.childNodes.length > 0) // Remove all child content which are added inside on the Div content divTip.removeChild(divTip.childNodes[0]); } // Invisible th Div (which removed all child content) divTip.style.visibility = "hidden"; } function MoveToolTipImage(event) { // Verify if the Div content already present? if (document.getElementById(sTooTipId)) { // Get the Div content var newDiv = document.getElementById(sTooTipId); if ('pageX' in event) { // all browsers except IE before version 9 var pageX = event.pageX; var pageY = event.pageY; } else { // IE before version 9 var pageX = event.clientX + document.documentElement.scrollLeft; var pageY = event.clientY + document.documentElement.scrollTop; } if (sToolTipPlacement == "Right") newDiv.style.left = (pageX + 17) + "px"; else // Left newDiv.style.left = (pageX - (parseInt(newDiv.style.width) + 17)) + "px"; // Portion of div when hide by browser top if ((pageY - (parseInt(newDiv.style.height) + 3)) < 0) // Showing below the cursor newDiv.style.top = pageY + "px"; else // Showing above the cursor newDiv.style.top = (pageY - (parseInt(newDiv.style.height) + 3)) + "px"; // Finally visibling the div which has the image newDiv.style.visibility = "visible"; } } // For showing tool tip function ShowToolTipImage(event, pId) { var newDiv = null; // Verify if the Div content already present? if (!document.getElementById(sTooTipId)) { // If not create a new Div element newDiv = document.createElement("div"); // Set the id for the Div element to refer further newDiv.setAttribute("id", sTooTipId); // Add it to the page document.body.appendChild(newDiv); } else { // Get the Div content which was invisible on HideTooTipImage function newDiv = document.getElementById(sTooTipId); } var url = ''; // Here the pId is the id of the image + a flag // (0 - when no image stored on the database or // 1 - when image stored on the in database) // which indicate whether the image required to show or not if (pId.split(",")[1] == 'False ') url = "Images/ImageNotAvailable.jpg"; else url = "GetImageHandler.ashx?ProductID=" + pId.split(",")[0]; var strImageContent = '<div class="border_preview"> ' + ' <div id="loader_container"> ' + ' <div id="loader"> ' + ' <div align="center">Loading image preview...</div> ' + ' <div id="loader_bg"> ' + ' <div id="progress"> </div>' + ' </div> ' + ' </div> ' + ' </div> ' + ' <div class="preview_temp_load"> ' + ' <img id="previewImage" onload="javascript:remove_loading();" src="' + url + '" border="0" width="100%" height="100%"> ' + ' </div> ' + '</div>'; newDiv.innerHTML = strImageContent; newDiv.style.zIndex = 2; newDiv.style.width = "340px"; newDiv.style.height = "80px"; newDiv.style.position = "absolute"; if ('pageX' in event) { // all browsers except IE before version 9 var pageX = event.pageX; var pageY = event.pageY; } else { // IE before version 9 var pageX = event.clientX + document.documentElement.scrollLeft; var pageY = event.clientY + document.documentElement.scrollTop; } if (sToolTipPlacement == "Right") newDiv.style.left = (pageX + 17) + "px"; else // Left newDiv.style.left = (pageX - (parseInt(newDiv.style.width) + 17)) + "px"; // Portion of div when hide by browser top if ((pageY - (parseInt(newDiv.style.height) + 3)) < 0) // Showing below the cursor newDiv.style.top = pageY + "px"; else // Showing above the cursor newDiv.style.top = (pageY - (parseInt(newDiv.style.height) + 3)) + "px"; // Finally visibling the div which has the image newDiv.style.visibility = "visible"; } var t_id = setInterval(animate, 20); var pos = 0; var dir = 2; var len = 0; function animate() { var elem = document.getElementById('progress'); if (elem != null) { if (pos == 0) len += dir; if (len > 32 || pos > 79) pos += dir; if (pos > 79) len -= dir; if (pos > 79 && len == 0) pos = 0; elem.style.left = pos + "px"; elem.style.width = len + "px"; } } function remove_loading() { var targelem = document.getElementById('loader_container'); targelem.style.display = 'none'; targelem.style.visibility = 'hidden'; }The required Style Sheet follows :
/*Styles*/ .border_preview{ z-index:100; position:absolute; background: #fff; border: 1px solid #444; padding:3px; width:100%; } #loader_container {text-align:left;position:absolute;} #loader { font-family:Tahoma, Helvetica, sans; font-size:10px; color:#000000; background-color:#FFFFFF; padding:10px 0 16px 0; margin:0 auto; display:block; width:135px; border:1px solid #6A6A6A; text-align:left; z-index:255; } #progress { height:5px; font-size:1px; width:1px; position:relative; top:1px; left:10px; background-color:#9D9D94 } #loader_bg { background-color:#EBEBE4; position:relative; top:8px;left:8px;height:7px; width:113px;font-size:1px } .title_h2 { color:#000; text-align: left; padding:12px 0 0 18px; margin:0; font-size:14px; } .preview_temp_load { vertical-align:middle; text-align:center; padding: 0px; } .preview_temp_load img{ vertical-align:middle; text-align:center; }The output of the code follows:
download the working copy of the source code in C# here and in VB here.
Can you send me the source code Please?
My email: b020910196@student.utem.edu.my
thx...
Your job is Awesome.... May i hv d Full Package of Source Code please...
my ID is sahil_gnr@hotmail.com
This will help me better...
THANXXX.....
data type 's("ProductImage") in database is varchar, it's a path,it's not image, example "Images/image1.jpg". How can I show this field?
Hi, Can you try the following url -
http://www.dotnettwitter.com/2010/11/sometime-back-i-got-assignment-to-show.html
Thirumalai M says:
7 May 2013 19:12
Hi, Can you try the following url -
http://www.dotnettwitter.com/2010/11/sometime-back-i-got-assignment-to-show.html
___________________________________
Can you send me a demo file? I'm trying very much but it's not work. So bad
My database in field "ProductImage" is a path.Data type is varchar.
"unable to cast object of type system.string to type system.byte[]".
Hi, I just tried the same example. It works fine.
For information, I am using Northwind database in this example. The Product table is used o fetch the values. I also added a new column in the table "ProductImage". So to test this example, you required to add that column. Run the below command to add the column.
alter table Products add ProductImage image
You required to store the image file in this column. You can use another post, which store images in the table.
http://www.dotnettwitter.com/2010/12/storing-images-into-database-and.html
Thank you very much
thanx for your help...it works fine