This example demonstrates how to implement a kind of an image gallery with an image preview.Image thumbnails are displayed by ASPxDataView that is used in Flow layout mode. In this mode, image thumbnails flow one after another, to fill the available page area within the browser window in the best possible way. When hovering a thumbnail, ASPxPopupControl is invoked to display a large (zoomed) image. During zoomed image loading, ASPxPopupControl displays a thumbnail image enlarged to the zoomed image size.The specificity of this example is that image previews are displayed with the help of a single ASPxPopupControl that is dynamically linked to multiple invoker elements via client code. The client SetPopupElementID method is used to associate ASPxPopupControl with multiple instances of a thumbnail image element placed within ASPxDataView's ItemTemplate.From this example, you can also learn how to dynamically generate two images - thumbnail and preview - from an original image and how to apply a watermark to a large preview image.
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using DevExpress.Web.ASPxClasses;
using DevExpress.Web.ASPxClasses.Internal;
using DevExpress.Web.ASPxDataView;
public partial class Examples_Default2 : System.Web.UI.Page {
protected void galleryDV_CustomJSProperties(object sender, CustomJSPropertiesEventArgs e) {
var itemDetails = new Dictionary<string, object>();
foreach(DataViewItem item in galleryDV.Items.GetVisibleItems()) {
var key = GetImageID(GetItemValue(item, "ID"));
itemDetails[key] = GetItemDetail(item);
}
e.Properties["cpItemDetails"] = itemDetails;
}
protected object GetItemDetail(DataViewItem item) {
Dictionary<string, object> itemDetail = new Dictionary<string, object>();
itemDetail.Add("description", GetItemValue(item, "Description"));
itemDetail.Add("highQualityImageUrl", GetItemValue(item, "LargeImageUrl"));
itemDetail.Add("imageWidth", GetItemValue(item, "Width"));
itemDetail.Add("imageHeight", GetItemValue(item, "Height"));
return itemDetail;
}
protected object GetItemValue(DataViewItem item, string fieldName) {
return DataBinder.Eval(item.DataItem, fieldName);
}
protected string GetImageID(object id) {
return string.Format("img_{0}", id);
}
}
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Examples_Default2" %>
<%@ Register Assembly="DevExpress.Web.v12.1" Namespace="DevExpress.Web.ASPxDataView"
TagPrefix="dx" %>
<%@ Register assembly="DevExpress.Web.v12.1" namespace="DevExpress.Web.ASPxPopupControl" tagprefix="dx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
function galleryDV_Init(s,e) {
InitializePopupElements();
}
function galleryDV_EndCallBack() {
InitializePopupElements();
}
function popup_Popup(s, e) {
var popupElement = s.GetCurrentPopupElement();
var itemDetail = galleryDV.cpItemDetails[popupElement.id];
var lowQualityImage = document.getElementById("lowQualityImage");
var description = document.getElementById("description");
var highQualityImageWrapper = document.getElementById("highQualityImageWrapper");
var highQualityImage = document.createElement("IMG");
highQualityImageWrapper.innerHTML = "";
highQualityImageWrapper.appendChild(highQualityImage);
highQualityImageWrapper.style.marginTop = "-" + itemDetail.imageHeight + "px";
highQualityImageWrapper.style.width = itemDetail.imageWidth + "px";
highQualityImageWrapper.style.height = itemDetail.imageHeight + "px";
lowQualityImage.src = popupElement.src;
lowQualityImage.width = itemDetail.imageWidth;
lowQualityImage.height = itemDetail.imageHeight;
lowQualityImage.alt = itemDetail.description;
highQualityImage.src = itemDetail.highQualityImageUrl;
highQualityImage.alt = itemDetail.description;
description.innerHTML = itemDetail.description;
s.UpdatePosition();
}
function InitializePopupElements() {
var imageIDs = [ ];
for(var id in galleryDV.cpItemDetails)
imageIDs.push(id)
popup.SetPopupElementID(imageIDs.join(";"));
}
</script>
</head>
<body>
<form id="form1" runat="server">
<p>To zoom a thumbnail image, move the mouse cursor over it.</p>
<div class="panel">
<dx:ASPxDataView ID="galleryDV" ClientInstanceName="galleryDV" runat="server"
EnableViewState="false" DataSourceID="XmlHomes"
OnCustomJSProperties="galleryDV_CustomJSProperties" Layout="Flow" PagerAlign="Justify"
ItemSpacing="0" ColumnCount="10" RowPerPage="2">
<ItemTemplate>
<div align="center" class="imageWrapper">
<a href="javascript:;">
<img id='<%# GetImageID(Eval("ID"))%>' src='<%# Eval("ImageUrl")%>' alt='<%# Eval("Description") %>' class="thumbnailImage" />
</a>
</div>
</ItemTemplate>
<PagerSettings ShowNumericButtons="true">
<AllButton Visible="False" />
<Summary Visible="false" />
<PageSizeItemSettings Visible="true" ShowAllItem="true"
Items="10, 20, 30, 60" />
</PagerSettings>
<ClientSideEvents Init="galleryDV_Init" EndCallback="galleryDV_EndCallBack" />
</dx:ASPxDataView>
</div>
<dx:ASPxPopupControl ID="popup" ClientInstanceName="popup" runat="server" EnableViewState="false" ShowHeader="false"
EnableAnimation="false" PopupHorizontalAlign="OutsideRight" PopupVerticalAlign="TopSides"
PopupAction="MouseOver" CloseAction="MouseOut" AppearAfter="0" DisappearAfter="0"
PopupHorizontalOffset="18" PopupVerticalOffset="-60">
<ContentCollection>
<dx:PopupControlContentControl>
<img id="lowQualityImage" src="" alt="" />
<div id="highQualityImageWrapper"></div>
<p id="description"></p>
</dx:PopupControlContentControl>
</ContentCollection>
<ClientSideEvents PopUp="popup_Popup" />
</dx:ASPxPopupControl>
<asp:XmlDataSource ID="XmlHomes" runat="server" DataFile="~/App_Data/Gallery.xml"
XPath="//dsImages/Image"></asp:XmlDataSource>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Drawing;
using System.Xml;
using System.Web.UI;
public class CreatorResources
{
const string watermarkText = "ASPxPopupControl Demo",
largeImagePostFix = "_large",
fontName = "Tahoma";
const float fontSize = 11;
readonly Color fontColor = Color.FromArgb(80, Color.Gray);
public void CreateThumbnailImages(Size thumbnailSize, Size largeSize, string originalImagesPath, string thumbnailImagePath, string xmlFileName) {
XmlDocument xmlDocument = CreateXmlDocument();
XmlElement rootElement = CreateXmlElement(xmlDocument, null, "dsImages");
var index = 0;
foreach(var imageSourceName in Directory.GetFiles(originalImagesPath)) {
var thumbnailImagefileName = Path.GetFileName(imageSourceName);
var largeImageFileName = thumbnailImagefileName.Insert(thumbnailImagefileName.IndexOf('.'), largeImagePostFix);
var actualLargeImageSize = new Size();
using(var imageSource = Bitmap.FromFile(imageSourceName)) {
using(var thumbnailImage = GetThumbnailImage(imageSource, thumbnailSize)) {
thumbnailImage.Save(thumbnailImagePath + thumbnailImagefileName);
}
using(var largeImage = GetThumbnailImage(imageSource, largeSize)) {
actualLargeImageSize.Width = largeImage.Width;
actualLargeImageSize.Height = largeImage.Height;
SetWatermark(largeImage);
largeImage.Save(thumbnailImagePath + largeImageFileName);
}
}
string relativeImagePath = string.Format("{0}/", new DirectoryInfo(thumbnailImagePath).Name);
XmlElement element = CreateXmlElement(xmlDocument, rootElement, "Image");
AddAttribute(xmlDocument, element, "ID", index);
AddAttribute(xmlDocument, element, "Description", Path.GetFileNameWithoutExtension(imageSourceName));
AddAttribute(xmlDocument, element, "ImageUrl", relativeImagePath + thumbnailImagefileName);
AddAttribute(xmlDocument, element, "LargeImageUrl", relativeImagePath + largeImageFileName);
AddAttribute(xmlDocument, element, "Width", actualLargeImageSize.Width);
AddAttribute(xmlDocument, element, "Height", actualLargeImageSize.Height);
index++;
}
xmlDocument.Save(xmlFileName);
}
Image GetThumbnailImage(Image image, Size size) {
var proportion = (float)size.Width / image.Width;
var width = size.Width;
var height = (int)(proportion * image.Height);
if(height > size.Height) {
proportion = (float)size.Height / image.Height;
height = size.Height;
width = (int)(proportion * image.Width);
}
return image.GetThumbnailImage(width, height, null, IntPtr.Zero);
}
void SetWatermark(Image image) {
using(Graphics graphics = Graphics.FromImage(image)) {
using(Font font = new Font(fontName, fontSize)) {
SizeF stringSize = graphics.MeasureString(watermarkText, font);
graphics.TranslateTransform(image.Width - stringSize.Height, image.Height);
graphics.RotateTransform(-90);
graphics.DrawString(watermarkText, font, new SolidBrush(fontColor), 5, -2);
}
}
}
XmlDocument CreateXmlDocument() {
XmlDocument document = new XmlDocument();
XmlDeclaration dec = document.CreateXmlDeclaration("1.0", null, null);
document.AppendChild(dec);
return document;
}
XmlElement CreateXmlElement(XmlDocument document, XmlElement rootElement, string elementName) {
XmlElement element = document.CreateElement(elementName);
if(rootElement == null)
document.AppendChild(element);
else
rootElement.AppendChild(element);
return element;
}
void AddAttribute(XmlDocument document, XmlElement element, string name, object value) {
XmlAttribute attribute = document.CreateAttribute(name);
attribute.InnerText = value.ToString();
element.Attributes.Append(attribute);
}
}
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports DevExpress.Web.ASPxClasses
Imports DevExpress.Web.ASPxClasses.Internal
Imports DevExpress.Web.ASPxDataView
Partial Public Class Examples_Default2
Inherits System.Web.UI.Page
Protected Sub galleryDV_CustomJSProperties(ByVal sender As Object, ByVal e As CustomJSPropertiesEventArgs)
Dim itemDetails = New Dictionary(Of String, Object)()
For Each item As DataViewItem In galleryDV.Items.GetVisibleItems()
Dim key = GetImageID(GetItemValue(item, "ID"))
itemDetails(key) = GetItemDetail(item)
Next item
e.Properties("cpItemDetails") = itemDetails
End Sub
Protected Function GetItemDetail(ByVal item As DataViewItem) As Object
Dim itemDetail As New Dictionary(Of String, Object)()
itemDetail.Add("description", GetItemValue(item, "Description"))
itemDetail.Add("highQualityImageUrl", GetItemValue(item, "LargeImageUrl"))
itemDetail.Add("imageWidth", GetItemValue(item, "Width"))
itemDetail.Add("imageHeight", GetItemValue(item, "Height"))
Return itemDetail
End Function
Protected Function GetItemValue(ByVal item As DataViewItem, ByVal fieldName As String) As Object
Return DataBinder.Eval(item.DataItem, fieldName)
End Function
Protected Function GetImageID(ByVal id As Object) As String
Return String.Format("img_{0}", id)
End Function
End Class
'INSTANT VB NOTE: This code snippet uses implicit typing. You will need to set 'Option Infer On' in the VB file or set 'Option Infer' at the project level:
<%@ Page Language="vb" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="Examples_Default2" %>
<%@ Register Assembly="DevExpress.Web.v12.1" Namespace="DevExpress.Web.ASPxDataView"
TagPrefix="dx" %>
<%@ Register assembly="DevExpress.Web.v12.1" namespace="DevExpress.Web.ASPxPopupControl" tagprefix="dx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
function galleryDV_Init(s,e) {
InitializePopupElements();
}
function galleryDV_EndCallBack() {
InitializePopupElements();
}
function popup_Popup(s, e) {
var popupElement = s.GetCurrentPopupElement();
var itemDetail = galleryDV.cpItemDetails[popupElement.id];
var lowQualityImage = document.getElementById("lowQualityImage");
var description = document.getElementById("description");
var highQualityImageWrapper = document.getElementById("highQualityImageWrapper");
var highQualityImage = document.createElement("IMG");
highQualityImageWrapper.innerHTML = "";
highQualityImageWrapper.appendChild(highQualityImage);
highQualityImageWrapper.style.marginTop = "-" + itemDetail.imageHeight + "px";
highQualityImageWrapper.style.width = itemDetail.imageWidth + "px";
highQualityImageWrapper.style.height = itemDetail.imageHeight + "px";
lowQualityImage.src = popupElement.src;
lowQualityImage.width = itemDetail.imageWidth;
lowQualityImage.height = itemDetail.imageHeight;
lowQualityImage.alt = itemDetail.description;
highQualityImage.src = itemDetail.highQualityImageUrl;
highQualityImage.alt = itemDetail.description;
description.innerHTML = itemDetail.description;
s.UpdatePosition();
}
function InitializePopupElements() {
var imageIDs = [ ];
for(var id in galleryDV.cpItemDetails)
imageIDs.push(id)
popup.SetPopupElementID(imageIDs.join(";"));
}
</script>
</head>
<body>
<form id="form1" runat="server">
<p>To zooming image, move the mouse cursor over one of the thumbnail images.</p>
<div class="panel">
<dx:ASPxDataView ID="galleryDV" ClientInstanceName="galleryDV" runat="server"
EnableViewState="false" DataSourceID="XmlHomes"
OnCustomJSProperties="galleryDV_CustomJSProperties" Layout="Flow" PagerAlign="Justify"
ItemSpacing="0" ColumnCount="10" RowPerPage="2">
<ItemTemplate>
<div align="center" class="imageWrapper">
<a href="javascript:;">
<img id='<%#GetImageID(Eval("ID"))%>' src='<%#Eval("ImageUrl")%>' alt='<%#Eval("Description")%>' class="thumbnailImage" />
</a>
</div>
</ItemTemplate>
<PagerSettings ShowNumericButtons="true">
<AllButton Visible="False" />
<Summary Visible="false" />
<PageSizeItemSettings Visible="true" ShowAllItem="true"
Items="10, 20, 30, 60" />
</PagerSettings>
<ClientSideEvents Init="galleryDV_Init" EndCallback="galleryDV_EndCallBack" />
</dx:ASPxDataView>
</div>
<dx:ASPxPopupControl ID="popup" ClientInstanceName="popup" runat="server" EnableViewState="false" ShowHeader="false"
EnableAnimation="false" PopupHorizontalAlign="OutsideRight" PopupVerticalAlign="TopSides"
PopupAction="MouseOver" CloseAction="MouseOut" AppearAfter="0" DisappearAfter="0"
PopupHorizontalOffset="18" PopupVerticalOffset="-60">
<ContentCollection>
<dx:PopupControlContentControl>
<img id="lowQualityImage" src="" alt="" />
<div id="highQualityImageWrapper"></div>
<p id="description"></p>
</dx:PopupControlContentControl>
</ContentCollection>
<ClientSideEvents PopUp="popup_Popup" />
</dx:ASPxPopupControl>
<asp:XmlDataSource ID="XmlHomes" runat="server" DataFile="~/App_Data/Gallery.xml"
XPath="//dsImages/Image"></asp:XmlDataSource>
</form>
</body>
</html>
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.IO
Imports System.Drawing
Imports System.Xml
Imports System.Web.UI
Public Class CreatorResources
Private Const watermarkText As String = "ASPxPopupControl Demo", largeImagePostFix As String = "_large", fontName As String = "Tahoma"
Private Const fontSize As Single = 11
Private ReadOnly fontColor As Color = Color.FromArgb(80, Color.Gray)
Public Sub CreateThumbnailImages(ByVal thumbnailSize As Size, ByVal largeSize As Size, ByVal originalImagesPath As String, ByVal thumbnailImagePath As String, ByVal xmlFileName As String)
Dim xmlDocument As XmlDocument = CreateXmlDocument()
Dim rootElement As XmlElement = CreateXmlElement(xmlDocument, Nothing, "dsImages")
Dim index = 0
For Each imageSourceName In Directory.GetFiles(originalImagesPath)
Dim thumbnailImagefileName = Path.GetFileName(imageSourceName)
Dim largeImageFileName = thumbnailImagefileName.Insert(thumbnailImagefileName.IndexOf("."c), largeImagePostFix)
Dim actualLargeImageSize = New Size()
Using imageSource = Bitmap.FromFile(imageSourceName)
Using thumbnailImage = GetThumbnailImage(imageSource, thumbnailSize)
thumbnailImage.Save(thumbnailImagePath & thumbnailImagefileName)
End Using
Using largeImage = GetThumbnailImage(imageSource, largeSize)
actualLargeImageSize.Width = largeImage.Width
actualLargeImageSize.Height = largeImage.Height
SetWatermark(largeImage)
largeImage.Save(thumbnailImagePath & largeImageFileName)
End Using
End Using
Dim relativeImagePath As String = String.Format("{0}/", New DirectoryInfo(thumbnailImagePath).Name)
Dim element As XmlElement = CreateXmlElement(xmlDocument, rootElement, "Image")
AddAttribute(xmlDocument, element, "ID", index)
AddAttribute(xmlDocument, element, "Description", Path.GetFileNameWithoutExtension(imageSourceName))
AddAttribute(xmlDocument, element, "ImageUrl", relativeImagePath & thumbnailImagefileName)
AddAttribute(xmlDocument, element, "LargeImageUrl", relativeImagePath & largeImageFileName)
AddAttribute(xmlDocument, element, "Width", actualLargeImageSize.Width)
AddAttribute(xmlDocument, element, "Height", actualLargeImageSize.Height)
index += 1
Next imageSourceName
xmlDocument.Save(xmlFileName)
End Sub
Private Function GetThumbnailImage(ByVal image As Image, ByVal size As Size) As Image
Dim proportion = CSng(size.Width) / image.Width
Dim width = size.Width
Dim height = CInt(Fix(proportion * image.Height))
If height > size.Height Then
proportion = CSng(size.Height) / image.Height
height = size.Height
width = CInt(Fix(proportion * image.Width))
End If
Return image.GetThumbnailImage(width, height, Nothing, IntPtr.Zero)
End Function
Private Sub SetWatermark(ByVal image As Image)
Using graphics As Graphics = Graphics.FromImage(image)
Using font As New Font(fontName, fontSize)
Dim stringSize As SizeF = graphics.MeasureString(watermarkText, font)
graphics.TranslateTransform(image.Width - stringSize.Height, image.Height)
graphics.RotateTransform(-90)
graphics.DrawString(watermarkText, font, New SolidBrush(fontColor), 5, -2)
End Using
End Using
End Sub
Private Function CreateXmlDocument() As XmlDocument
Dim document As New XmlDocument()
Dim dec As XmlDeclaration = document.CreateXmlDeclaration("1.0", Nothing, Nothing)
document.AppendChild(dec)
Return document
End Function
Private Function CreateXmlElement(ByVal document As XmlDocument, ByVal rootElement As XmlElement, ByVal elementName As String) As XmlElement
Dim element As XmlElement = document.CreateElement(elementName)
If rootElement Is Nothing Then
document.AppendChild(element)
Else
rootElement.AppendChild(element)
End If
Return element
End Function
Private Sub AddAttribute(ByVal document As XmlDocument, ByVal element As XmlElement, ByVal name As String, ByVal value As Object)
Dim attribute As XmlAttribute = document.CreateAttribute(name)
attribute.InnerText = value.ToString()
element.Attributes.Append(attribute)
End Sub
End Class