Friday, March 30, 2012

How to get distinct values from the List<T> with LINQ

Recently I was working with data from a generic List<T> and one of my objectives is to get the distinct values that is found in the List. Consider that we have this simple class that holds the following properties:

public class Product
{
        public string Make { get; set; }
        public string Model { get; set; } 

}

 

Now in the page code behind we will create a list of product by doing the following:

private List<Product> GetProducts() { 

    List<Product> products = new List<Product>(); 
    Product p = new Product(); 

    p.Make = "Samsung"; 
    p.Model = "Galaxy S 1"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Samsung"; 
    p.Model = "Galaxy S 2"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Samsung"; 
    p.Model = "Galaxy Note"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Apple"; 
    p.Model = "iPhone 4"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Apple"; 
    p.Model = "iPhone 4s"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "HTC"; 
    p.Model = "Sensation"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "HTC"; 
    p.Model = "Desire"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Nokia"; 
    p.Model = "Some Model"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Nokia"; 
    p.Model = "Some Model"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Sony Ericsson"; 
    p.Model = "800i"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Sony Ericsson"; 
    p.Model = "800i"; 
    products.Add(p); 

    return products; 

}

 

And then let’s bind the products to the GridView.

protected void Page_Load(object sender, EventArgs e) { 
           if (!IsPostBack) { 
               Gridview1.DataSource = GetProducts();
               Gridview1.DataBind(); 
           } 
}

 

Running the code will display something like this in the page:

linq1

Now what I want is to get the distinct row values from the list. So what I did is to use the LINQ Distinct operator and unfortunately it doesn't work. In order for it work is you must use the overload method of the Distinct operator for you to get the desired results. So I’ve added this IEqualityComparer<T> class to compare values:

class ProductComparer : IEqualityComparer<Product> 
{ 
        public bool Equals(Product x, Product y) { 
            if (Object.ReferenceEquals(x, y)) return true; 

            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
                return false; 

            return x.Make == y.Make && x.Model == y.Model; 
        } 

        public int GetHashCode(Product product) { 
            if (Object.ReferenceEquals(product, null)) return 0; 
            int hashProductName = product.Make == null ? 0 : product.Make.GetHashCode(); 
            int hashProductCode = product.Model.GetHashCode(); 
            return hashProductName ^ hashProductCode; 
        } 

}

 

After that you can then bind the GridView like this:

protected void Page_Load(object sender, EventArgs e) { 
            if (!IsPostBack) { 
                Gridview1.DataSource = GetProducts().Distinct(new ProductComparer()); 
                Gridview1.DataBind(); 
            } 
}

 

Running the page will give you the desired output below:

linq2

As you notice, it now eliminates the duplicate rows in the GridView. Now what if we only want to get the distinct values for a certain field. For example I want to get the distinct “Make” values such as Samsung, Apple, HTC, Nokia and Sony Ericsson and populate them to a DropDownList control for filtering purposes. I was hoping the the Distinct operator has an overload that can compare values based on the property value like (GetProducts().Distinct(o => o.PropertyToCompare). But unfortunately it doesn’t provide that overload so what I did as a workaround is to use the GroupBy,Select and First LINQ query operators to achieve what I want.

Here’s the code to get the distinct values of a certain field.

protected void Page_Load(object sender, EventArgs e) { 
            if (!IsPostBack) {
                DropDownList1.DataSource = GetProducts().GroupBy(o => o.Make).Select(o => o.First()); 
                DropDownList1.DataTextField = "Make"; 
                DropDownList1.DataValueField = "Model"; 
                DropDownList1.DataBind(); 
            } 

}

Running the code will display the following output below:

linq3

 

That’s it! I hope someone find this post useful!

Friday, February 17, 2012

Book Review - .NET 4.0 Generics Beginner's Guide

0782OT_.NET Generics Beginner's Guide_0

Few days ago I have received an invitation from Packt Publishing to review this book. I myself is a big fan of Generics and is very interested about it, so I've decided to give it a go. Thank you for letting me review this interesting book.

.NET 4.0 Generics (Packt Publishing) is written by Sudipta Mukherjee. The book is primarily targeted to beginners and intermediate programmers who want to know what .NET Generics is all about and how it can help solved real world problems.

The book covers the fundamental concepts of type-safety, generic methods and generic containers and highlights the importance of generic collections and generic class. The good thing about this book is that knowledge in .NET Generics is not a requirement for as long as you are familiar with C# program constructs such as variable declarations, looping, casting and so on.

Chapter 1 talks about the beauty of Generics. Sudipta highlights the main reasons why Generics is important by illustrating practical examples and algorithms. Chapter 2 does a very good job of illustrating the different kinds of generic list by showing some real world examples which I've learned a lot =}. Basically it talks about generic containers and related methods and explained the details about types of generic lists and how to use them to solved real world problems. You will see in this chapter how simple lists can deliver amazing results avoiding any typecasting woes and boosting performance at the same time. It also covers how to create your own custom generic list-based containers. Chapter 3 takes a much more in depth look about .NET Generics Dictionary-based containers and talks about the types of Generic Associative Structures, how to create your own GAS and how to use them by illustrating practical examples. Chapter 4 talks about a brief introduction about LINQ (Language Integrated Query) and its cool features and showed the power of LINQ by presenting practical examples on how to use LINQ to query generic collections. This chapter has a lot of knowledge packed into and even myself was amazed about the real beauty LINQ for querying collections. Chapter 5 of this book covers how to monitor a changed using Observable Collections. By changed I meant "physical changes of elements being added in the Generic Collections. Chapter 6 covers Concurrent Collections and how this can make writing synchronized code easy. Chapter 7 and 8 discussed about data structures and algorithms by using some of the well known Generic Collections API such as the Wintellect's Power Collections and C5 APIs.This chapter highlights the API's available algorithms that are difficult to reproduce with the standard LINQ operators. The last two chapters on this book covers the different patterns, best practices and performance analysis to help you pick the correct Generic collection and algorithm for efficiently solving a problem. I was delighted on how the author presented the benchmarking for the performance analysis, it really helped me a lot finding the best generic containers to use in certain situations.

Overall I was really impressed on how Sudipta manage to apply his expertise and understanding about the subject to the content and style of his book. The book is very well constructed and each chapter covers the right amount of depth and by providing some real world examples with detailed explanations. Chapters are also completed with exercises and questions to test your growing knowledge about generic collections.

I really enjoyed reading this book and I have learned a lot of things about generics ~ I wish I could get a hard copy of this book =). My confusions as to what type of generic to use and what's the best for certain scenarios has been cleared and answered after reading this book. If you are a beginner or an intermediate programmer who want to know what .NET Generics is all about and why is it important or if you are an architect or a senior programmer who wants to define coding standards in your team then I highly recommend to get yourself a copy of it.

Wednesday, February 15, 2012

Wijmo v2 - New UI toolkit for HTML5 development

Good news to all Web devs, ComponentOne has released Wijmo v2. A complete kit of 40+ jQuery UI widgets including everything you'll need to build rich HTML5 applications in a cinch. If you know jQuery, you know Wijmo. This release provides unmatched functionality with 14 hot, NEW widgets including:

  • For data visualization - Area, Bubble, Scatter, and Composite Charts, as well as Linear and Radial Gauges
  • Powerful Events Calendar with HTML5 offline storage
  • For rich media - Lightbox, Gallery, and Video Player

Download the Wijmo toolkit trial complete with sample code and add the widgets to your applications. Or, explore the HTML5 widgets in the Wijmo demo.

You can download Wijmo v2 for Free. Enjoy!

Friday, February 03, 2012

What will you be if computers weren't in existence?

Yeah it's a tough question especially since most of us across the globe, both young and old heavily rely on computers and the internet . Today, life would be virtually impossible without it. When I was in elementary school I always dreamed of becoming an artist. I loved to paint and draw because I can express my thoughts and emotions through art. But things changed after I graduated  in high school because my family couldn't afford to send me to university. I earned my BS degree because I got a scholarship from STI to study computer science. So now I work as a web developer. But to answer the question, if computers didn't exist then I would be a carpenter and a farmer then I would create a machine from wood that will compile codes made out of paper that will produce kernels of corn ~ just kidding on that part =D. Seriously I would definitely be an architect or an artist because being an artist is having the freedom to express your personality through art. The picture below is one of my drawings which I’ve drawn a long long time ago. Not pretty cool but it rocks! :D

mydrawing

How about you? What do you think will you be doing now if computers weren't in existence?

 

Technorati Tags: ,

Wednesday, February 01, 2012

Finally! ProudMonkey Controls is out on CodePlex!

I've been receiving requests for the source code of my MessageBox controls for ASP.NET and so I've decided to upload my project in CodePlex so everyone can use it. You can check and download the controls here: http://proudmonkeycontrols.codeplex.com/

Feel free to visit my project page and provide your valuable feedback!

Thanks!

Using ProudMonkey ConfirmBox Control in GridView

There are times that we need to prompt the users when doing certain actions on the page. One practical example is to confirm the user when deleting a certain record just like what I have demonstrated awhile back about Displaying a Confirmation Message on GridView Deleting. If you noticed on that demo I simply use plain JavaScript to display the confirmation message. In this post I’m going to demonstrate how to use the ConfirmBox control in delete scenario.

Note that just for the simplicity of this demo I’m just going to create a dummy data as the DataSource for the GridView. If you are working with live data from database then you may want to check these previous articles about:

To get started let’s go ahead and set up the UI (HTML mark-up). For simplicity I set up the mark-up like this:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master"
                  AutoEventWireup="true" 
                  CodeBehind="GridView.aspx.cs"
                  Inherits="WebAppDemo.GridView" %>
<%@ Register Assembly="AjaxControlToolkit" 
             Namespace="AjaxControlToolkit" 
             TagPrefix="asp" %>
<%@ Register assembly="ProudMonkey.Common.Controls"
             namespace="ProudMonkey.Common.Controls" 
             tagprefix="cc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" >
    </asp:ToolkitScriptManager>
    <cc1:ConfirmBox ID="ConfirmBox1" runat="server" />
    <asp:Label ID="lblMessageDisplay" runat="server" ForeColor="Green" />
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" >
        <Columns>
                <asp:BoundField DataField="ID" />
                <asp:BoundField DataField="ProductName" HeaderText="Product Name" />
                <asp:TemplateField>
                <ItemTemplate>
                    <asp:TextBox ID="txtPrice" runat="server" Text='<%# Eval("Price") %>' />
                </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                <ItemTemplate>
                    <asp:TextBox ID="txtAmount" runat="server" Text='<%# Eval("Amount") %>' />
                </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="btnDelete" runat="server" 
                                Text="Delete" 
                                OnClientClick="ShowConfirmBox(this,'Are you sure?');return false;" 
                                onclick="BtnDelete_Click" /> 
                </ItemTemplate>
                </asp:TemplateField>
        </Columns>
    </asp:GridView>
</asp:Content>

 

Obviously the page above make use of MasterPage and basically contains the ToolScriptManager, ConfirmBox, Label and GridView. The ToolScriptManager is necessary since the ConfirmBox control uses the ASP.NET Ajax Modal popup control. The Label is just for displaying the message and the GridView is for displaying the data.

Here’s the whole code behind part of the demo:

using System;
using System.Web.UI.WebControls;
using System.Data;

namespace WebAppDemo {
    public partial class GridView : System.Web.UI.Page {

        private DataTable GetSampleData() {

            //NOTE: THIS IS JUST FOR DEMO
            //If you are working with database
            //You can query your actual data and fill it to the DataTable
            DataTable dt = new DataTable();
            DataRow dr = null;

            //Create DataTable columns
            dt.Columns.Add(new DataColumn("ID", typeof(string)));
            dt.Columns.Add(new DataColumn("ProductName", typeof(string)));
            dt.Columns.Add(new DataColumn("Price", typeof(string)));
            dt.Columns.Add(new DataColumn("Amount", typeof(string)));

            //Create Row for each columns
            dr = dt.NewRow();
            dr["ID"] = 1;
            dr["ProductName"] = "Proudct 1";
            dr["Price"] = "100";
            dr["Amount"] = "10";

            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 2;
            dr["ProductName"] = "Product 2";
            dr["Price"] = "200";
            dr["Amount"] = "2";

            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 3;
            dr["ProductName"] = "Product 3";
            dr["Price"] = "50";
            dr["Amount"] = "10";

            dt.Rows.Add(dr);
            return dt;
        }
        

        private void BindGrid(DataTable source) {
            GridView1.DataSource = source;
            GridView1.DataBind();
        }

        private DataTable UpdateTable(DataTable source, int rowIndex) {
            for (int i = 0; i < GridView1.Rows.Count; i++) {
                TextBox tb1 = (TextBox)GridView1.Rows[i].Cells[2].FindControl("txtPrice");
                TextBox tb2 = (TextBox)GridView1.Rows[i].Cells[3].FindControl("txtAmount");
                source.Rows[i]["Price"] = tb1.Text;
                source.Rows[i]["Amount"] = tb2.Text;
            }
            source.Rows.RemoveAt(rowIndex);
            return source;
        }

        protected void Page_Load(object sender, EventArgs e) {
            if (!IsPostBack) {
                ViewState["COPY"] = GetSampleData();
                BindGrid(GetSampleData());
            }
        }

        protected void BtnDelete_Click(object sender, EventArgs e) {
            if (ViewState["COPY"] != null) {
                DataTable dt = (DataTable)ViewState["COPY"];
                Button btnDelete = (Button)sender;
                GridViewRow gvRow = (GridViewRow)btnDelete.NamingContainer;
                BindGrid(UpdateTable(dt, gvRow.RowIndex));

                lblMessageDisplay.Text = "Record deleted!";
            }
        }
    }
}

 

Since I didn’t use database for storing the data you may notice that I use ViewState to store the data across postbacks as you see in Page_Load event. The UpdateTable() method is responsible for handling the deletion. You may also notice that before the row is being removed it updates first the data, this is to ensure that the data on the TextBox are retained on postbacks.

Here’s the page output when you run the code.

Initial load

pm1

After clicking the Delete button

pm2

After clicking the YES button

pm3 

 

Enjoy!!!

Technorati Tags: ,

Wednesday, January 25, 2012

Closing my Blog at CodeASP.Net

I will be closing my blog (http://codeasp.net/blogs/Vinz) to avoid cross posting of contents and traffic. This means that I will not be posting there anymore. But please note that by stop blogging there doesn't mean I will stop contributing to the codeasp.net community, of course I will still be moderating posts and participating in the forums and try my best to answer to questions to the best that I can and whenever time permits. See you guys there!!! =}

I've recently updated the look and feel of this blog and updated each content to make it more readable and clean. I hope you like it.

Tuesday, January 24, 2012

ProudMonkey Controls will be in CodePlex soon

I will be hosting this project in http://www.codeplex.com/ as open source project. I’m working on it so stay tuned! =}

Thursday, January 12, 2012

Using MessageBox Control Outside UpdatePanel Control

Few days ago I wrote a simple demo about “Using ProudMonkey Controls with ASP.NET AJAX Update Panel”. One small problem is that if for some reasons you will place the MessageBox control outside UpdatePanel then you’ll notice that the MessageBox will not display properly in the page.

So if you were setting your html mark-up like this:

<%@ Register Assembly="AjaxControlToolkit" 
             Namespace="AjaxControlToolkit" 
             TagPrefix="asp" %>
<%@ Register Assembly="ProudMonkey.Common.Controls"
             Namespace="ProudMonkey.Common.Controls"
             Tagprefix="cc1" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
        </asp:ToolkitScriptManager>
        <cc1:MessageBox ID="MessageBox1" runat="server"  />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server"
                            onclick="Button1_Click"
                             Text="Show Message" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
</body>
</html>

 

And calling the MessageBox at Button click event:

protected void Button1_Click(object sender, EventArgs e){
      MessageBox1.ShowError("Test ERROR Message!");
} 

 

You will end up getting something like this in the page:

 

m1

 

The reason why it happened because when you do a PostBack some of the attributes defined within MessageBox will not be loaded properly (e.g the src and style). To resolved the issue we can set up Triggers in the UpdatePanel to do postback. Here’s the sample demo below for your reference:

ASPX:

<%@ Register Assembly="AjaxControlToolkit"
             Namespace="AjaxControlToolkit" 
             TagPrefix="asp" %>
<%@ Register Assembly="ProudMonkey.Common.Controls"
             Namespace="ProudMonkey.Common.Controls"
             Tagprefix="cc1" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" >
        </asp:ToolkitScriptManager>
        <cc1:MessageBox ID="MessageBox1" runat="server"  />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server"
                            onclick="Button1_Click"
                            Text="Show Message" />
            </ContentTemplate>
           <Triggers>
                <asp:PostBackTrigger ControlID="Button1" />
            </Triggers>
        </asp:UpdatePanel> 
    </form>
</body>
</html>

Code Behind:

protected void Button1_Click(object sender, EventArgs e){
     MessageBox1.ShowError("Test ERROR Message!");
}  

 

Running the page will display the MessageBox properly. Here’s a sample screen shot below:

m2

That’s it! I hope someone find this post useful.

Wednesday, January 11, 2012

Show Large Image on Mouseover with jQuery

I’ve been seeing many members in the forums asking how to display a large copy of the image on mouseover. Some of them are displaying the image in a Repeater, GridView or DataList control. I didn’t find any direct solution that shows the scenario they wanted so I thought of writing this post to demonstrate how to go about it. I know there are lot of ways of doing/implementing a solution for this scenario and this is just one them. In this example I’m going to use the DataList control for displaying the data along with the images.

To get started let’s go a head and set-up the HTML mark-up. Just for the simplicity of this demo, I’ve just set up the mark-up this way:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:DataList ID="DataList1" runat="server" RepeatColumns="2" RepeatDirection="Vertical">
        <ItemTemplate>
                <table>
                    <tr>
                        <td><asp:Image ID="imgProduct" runat="server" ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ProductImage") %>' style="width:100px; height:100px;" /></td>
                        <td> 
                            <asp:Label ID="lblProduct" Text='<%# DataBinder.Eval(Container.DataItem, "ProductName") %>' runat="server" />
                            <br />
                            <asp:Label ID="lblPrice" Text='<%# DataBinder.Eval(Container.DataItem, "Price") %>' runat="server" />
                            <br />
                            <asp:TextBox ID="txtQty" runat="server"></asp:TextBox>
                        </td>
                    </tr>
                </table>
        </ItemTemplate>
</asp:DataList>
</asp:Content>

 

As you can see there’s really no fancy about the mark-up above. It just contain a DataList control with Image, TextBox and Label controls defined within it. You also notice that each control are binded with the fields that we want to display. Now let’s go ahead and populate the DataList with a sample data. Here’s the code behind part below:

using System;
using System.Data;

namespace WebAppDemo {
    public partial class Repeater : System.Web.UI.Page {

        private DataTable GetSampleData() {

            //NOTE: THIS IS JUST FOR DEMO
            //If you are working with database
            //You can query your actual data and fill it to the DataTable

            DataTable dt = new DataTable();
            DataRow dr = null;

            //Create DataTable columns
            dt.Columns.Add(new DataColumn("ID", typeof(string)));
            dt.Columns.Add(new DataColumn("ProductImage", typeof(string)));
            dt.Columns.Add(new DataColumn("ProductName", typeof(string)));
            dt.Columns.Add(new DataColumn("Price", typeof(string)));

            //Create Row for each columns
            dr = dt.NewRow();
            dr["ID"] = 1;
            dr["ProductName"] = "Product 1";
            dr["ProductImage"] = "~/Images/Image1.jpg";
            dr["Price"] = "100";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 2;
            dr["ProductName"] = "Product 2";
            dr["ProductImage"] = "~/Images/Image2.jpg";
            dr["Price"] = "200";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 3;
            dr["ProductName"] = "Product 3";
            dr["ProductImage"] = "~/Images/Image3.jpg";
            dr["Price"] = "50";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 3;
            dr["ProductName"] = "Product 4";
            dr["ProductImage"] = "~/Images/Image4.jpg";
            dr["Price"] = "500";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 3;
            dr["ProductName"] = "Product 5";
            dr["ProductImage"] = "~/Images/Image5.jpg";
            dr["Price"] = "70";
            dt.Rows.Add(dr);

            return dt;
        }

        protected void Page_Load(object sender, EventArgs e) {
            if (!IsPostBack) {
                DataList1.DataSource = GetSampleData();
                DataList1.DataBind();
            }
        }       
    }
}

 

Running the code will display something like this in the page:

datalist0

Now that we already have our data in placed let’s proceed implementing the mouseover functionality with jQuery. To start using jQuery then register the following script at the very top of the <head> section of the page or if you are using master page then add it the very top of  the content head section.

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" ></script>

As you can see I'm using Google AJAX API CDN to host the jQuery file for some reasons. You can also download the jQuery here and host it in your server if you'd like. Now add the following mark-up at the top your DataList.

    <span id="coord"></span>
    <div id="divImageDisplay" style="position:absolute;">   
    </div>

The divImageDisplay is where we display the large copy of the Image when we hover on each image from the DataList. We will then display the coordinate values in the label to see the top and left value. Okay here's the full script below for the mouseover functionality:

<script type="text/javascript">
        function getTop(e) {
            var offset = e.offsetTop;
            if (e.offsetParent != null) offset += getTop(e.offsetParent);
            return offset;
        }
        function getLeft(e) {
            var offset = e.offsetLeft;
            if (e.offsetParent != null) offset += getLeft(e.offsetParent);
            return offset;
        }
        function hideDivImageDisplay() {
            $('#divImageDisplay').html();
        }

        function showDivImageDisplay(img) {
            var grid = $('#<%=DataList1.ClientID %>');
            var leftPos = getLeft(img) + 80;
            var topPos = getTop(img) + 20;
            $('#divImageDisplay').offset({ top: topPos, left: leftPos })
            $('#divImageDisplay').html("<img src='" + img.src + "' width='300px' height='300px'/>");

            //print the coordinates
            $('#coord').text('Image ID: ' + img.id + ' left: ' + leftPos + ' top: ' + topPos);
        }
  
</script>

 

The getTop() function gets the top position coordinate value of the hovered image. The  getLeft() function gets the left position coordinate value. The hideDivImageDisplay() function will hide the div by clearing out the elements within it using the .html() jQuery function. The showDivImageDisplay() function is where we set the position of the divImageDisplay to display below each image from the DataList.

Now let’s put it all together. Here’s the full ASPX mark-up below:

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">

<script type="text/javascript">
        function getTop(e) {
            var offset = e.offsetTop;
            if (e.offsetParent != null) offset += getTop(e.offsetParent);
            return offset;
        }
        function getLeft(e) {
            var offset = e.offsetLeft;
            if (e.offsetParent != null) offset += getLeft(e.offsetParent);
            return offset;
        }
        function hideDivImageDisplay() {
            $('#divImageDisplay').html();
        }

        function showDivImageDisplay(img) {
            var grid = $('#<%=DataList1.ClientID %>');
            var leftPos = getLeft(img) + 80;
            var topPos = getTop(img) + 20;
            $('#divImageDisplay').offset({ top: topPos, left: leftPos })
            $('#divImageDisplay').html("<img src='" + img.src + "' width='300px' height='300px'/>");

            //print the coordinates
            $('#coord').text('Image ID: ' + img.id + ' left: ' + leftPos + ' top: ' + topPos);
        }
  
</script>

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <span id="coord"></span>
    <div id="divImageDisplay" style="position:absolute;">   
    </div>

    <asp:DataList ID="DataList1" runat="server" RepeatColumns="2" RepeatDirection="Vertical">
        <ItemTemplate>
                <table>
                    <tr>
                        <td><asp:Image ID="imgProduct" runat="server" ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ProductImage") %>' style="width:100px; height:100px;" onmouseover="showDivImageDisplay(this);" onmouseout="hideDivImageDisplay();" /></td>
                        <td> 
                            <asp:Label ID="lblProduct" Text='<%# DataBinder.Eval(Container.DataItem, "ProductName") %>' runat="server" />
                            <br />
                            <asp:Label ID="lblPrice" Text='<%# DataBinder.Eval(Container.DataItem, "Price") %>' runat="server" />
                            <br />
                            <asp:TextBox ID="txtQty" runat="server"></asp:TextBox>
                        </td>
                    </tr>
                </table>
        </ItemTemplate>
</asp:DataList>
</asp:Content>

Here’s the output below when running the page:

datalist

 

That’s it! I hope someone find this post useful!