Introduction
I just got back from my honeymoon. My wife and I went to Europe for about two weeks, hitting up London, Paris, and
Amsterdam. Neither of us had been on that side of the Atlantic before, so, not surprisingly, we took a lot of
pictures with our digital camera. Well over 400, in fact. Over the weekend, I began to sort through these images,
cropping, resizing, and fine tuning various pictures of particular interest. What I want is to be able to easily
share these pictures with families and friends. Ideally, I'd like to be able to simply dump these images in
a directory, and provide a user-friendly interface for navigating through the images.
In order to accomplish this I could have opted to use an image gallery Web application program, like
nGallery project. nGallery is an open-source ASP.NET Web application that
provides a number of features for creating and maintaining an online image gallery. It is skinnable, has a Web
front-end for allowing an administrator to upload images, has thumbnailing of images, and a bevy of other nifty
things worth checking out. The disadvantage of this approach, though, is that it takes time to download the
application and configure it, not to mention the time needed to create the album and upload the hundreds of pictures
through the Web-based interface. Granted, this wouldn't take that long, but I wanted to be able to just
FTP images to a directory and be done.
Given this, I decided to create a simple ASP.NET Web page that would display a slide show of image files in
the same directory that it exists in. Therefore, to display a slideshow of images, all you have to do is the following:
Create a directory on a Web site and upload the images to display (via FTP, for example)
Copy the Default.aspx ASP.NET Web page to the same directory the images were uploaded
That's it! In this article we'll look at how to create the Default.aspx page. (Take a moment to check
out the live demo.) In a future article,
we'll see how we can eliminate step 2 altogether by turning Default.aspx into an HTTP handler.
(For more on HTTP handlers, check out my article: Serving
Dynamic Content with HTTP Handlers.)
Getting the Image Files in the Current Directory
In order to display a slideshow of the images in a directory, we must be able to retrieve a list of images in a
given directory. This can be accomplished by using the DirectoryInfo class in the System.IO
namespace. To use the DirectoryInfo class you create a new DirectoryInfo class, passing in
the path of the directory you want to get the files from in the DirectoryInfo constructor. The
DirectoryInfo class has a GetFiles() method that will return an array of FileInfo
instances. Each FileInfo instance contains information about a file in the specified directory.
The following snippet from Default.aspx shows how the Page_Load event handler populates
an array of FileInfo objects from the current directory. (The current directory is retrieved using
Server.MapPath("").)
Sub Page_Load(sender as Object, e as EventArgs)
'Get list of images
Dim dirInfo as New DirectoryInfo(Server.MapPath(""))
Dim images() as FileInfo = FilterForImages(dirInfo.GetFiles())
...
End Sub
Realize that the GetFiles() method will return all files in the specified directory. This method
can also be passed in a string, specifying a search pattern to limit the results, such as *.jpg. Rather
than just grab back the .jpg files, I get all of the files, since the slideshow should also show
non-JPEG images, such as GIFs and PNGs. The FilterForImages() function searches through the passed-in
array and returns an array of FileInfo objects that are image files.
Function FilterForImages(images() as FileInfo) as FileInfo()
Dim newImages as New ArrayList(images.Length)
Dim i as Integer
For i = 0 to images.Length - 1
If Path.GetExtension(images(i).Name.ToLower()) = ".jpg" OrElse _
Path.GetExtension(images(i).Name.ToLower()) = ".jpeg" OrElse _
Path.GetExtension(images(i).Name.ToLower()) = ".png" OrElse _
Path.GetExtension(images(i).Name.ToLower()) = ".gif" then
newImages.Add(images(i))
End If
Next
Return CType(newImages.ToArray(GetType(FileInfo)), FileInfo())
End Function
As you can see here, the passed-in array is looped through. If the file extension of the current FileInfo
object is .jpg, .jpeg, .png, or .gif, the image is added to
the newImages ArrayList. Any non-image files - such as Default.aspx or other ASP.NET Web pages -
are skipped over. Finally, the function returns the underlying array in the ArrayList.
Displaying the Current Image
Recall that my goal here was to display the images in a directory in a slideshow. Therefore, Default.aspx
needs to display a specific image from the directory and provide next and previous links to allow the user to step
through the image slideshow. To accomplish this, we need to somehow keep track of what image needs to be displayed (that is,
what image is the "current" image). I chose to use a querystring variable, N, which specifies the index
of the image in the images array to display.
In order to display the image in the Web page, I used an Image Web control. In the Page_Load event handler,
the querystring is examined and the appropriate image from the images array is displayed, based on the
querystring value. The following code and markup illustrates this:
Source Code Portion
Sub Page_Load(sender as Object, e as EventArgs)
...
'Determine the current image to show
Dim imgIndex as Integer = 0
If Not Request.QueryString("N") is Nothing AndAlso _
IsNumeric(Request.QueryString("N")) then
imgIndex = CInt(Request.QueryString("N"))
End If
currentImgTitle.Text = "You are Viewing: " & _
Path.GetFileNameWithoutExtension(images(imgIndex).Name) & _
" (" & imgIndex + 1 & " of " & images.Length & ")"
currentImg.ImageUrl = Path.GetFileName(images(imgIndex).Name)
...
End Sub
HTML Markup Portion
<asp:Label runat="server" id="currentImgTitle" /><br />
<asp:Image runat="server" id="currentImg" />
As you can see here, the HTML portion of Default.aspx contains a Label Web control (currentImgTitle)
as well as an Image Web control (currentImg). These two Web controls are configured in the
Page_Load event handler, their values being determined by the querystring value N. Now,
when the page is first visited, there won't be any querystring value; in this case, the default of 0 is used, which displays
the first image in the directory. (Realize that the images returned by GetFiles() are sorted alphabetically.)
Stepping through the Images
At this point we have examined how to retrieve the image files from a directory and how to display the current image.
All that remains to be done is to provide a mechanism for the user to step through the images in the slideshow.
Default.aspx provides two means:
Via Next/Previous hyperlinks
Via a list of all of the images in the directory. This lets the user quickly jump to a particular image.
The Next/Previous links are implemented as HyperLink Web controls, and their NavigateUrl properties are
set in the Page_Load event handler, since what URL the link points to depends on the current value of
N in the querystring.
Source Code Portion
Sub Page_Load(sender as Object, e as EventArgs)
...
If imgIndex > 0 then
lnkPrev.NavigateUrl = "Default.aspx?N=" & imgIndex - 1
End If
If imgIndex < images.Length - 1 then
lnkNext.NavigateUrl = "Default.aspx?N=" & imgIndex + 1
End If
...
End Sub
HTML Markup Portion
<asp:HyperLink runat="server" id="lnkPrev" Text="< Previous" /> |
<asp:HyperLink runat="server" id="lnkNext" Text="Next >" />
Notice that the HyperLinks' NavigateUrl properties are only set if the index of the current image being
displayed meets certain criteria. That is, we don't display a previous link if the user is viewing the first image
(that is, if the image index is 0). Similarly, we don't display a next link if the user is viewing the last image
in the array.
In addition to Next/Previous links, Default.aspx also contains a DataList that lists all of the images
as hyperlinks, allowing the user to quickly jump to a particular image from the set of images.
Source Code Portion
Sub Page_Load(sender as Object, e as EventArgs)
...
dlIndex.DataSource = images
dlIndex.DataBind()
End Sub
Sub dlIndex_ItemDataBound(sender as Object, e as DataListItemEventArgs)
If e.Item.ItemType = ListItemType.Item OrElse _
e.Item.ItemType = ListItemType.AlternatingItem then
'Get the Hyperlink
Dim hl as HyperLink = CType(e.Item.FindControl("lnkPic"), HyperLink)
'Set the Text and Navigation properties
hl.Text = Path.GetFileNameWithoutExtension(_
DataBinder.Eval(e.Item.DataItem, "Name").ToString()) & _
" (" & _
Int(DataBinder.Eval(e.Item.DataItem, "Length") / 1000) & _
" KB)"
hl.NavigateUrl = "Default.aspx?N=" & e.Item.ItemIndex
End If
End Sub
HTML Markup Portion
<asp:DataList runat="server" id="dlIndex"
OnItemDataBound="dlIndex_ItemDataBound"
RepeatColumns="3">
<ItemTemplate>
<li><asp:HyperLink runat="server" id="lnkPic" /></li>
</ItemTemplate>
</asp:DataList>
The DataList's ItemTemplate contains a simple HyperLink Web control. In the Page_Load event
handler, the array of FileInfo instances is bound to the DataList. As each particular FileInfo instance
is bound to the DataList, the DataList's ItemDataBound event fires, and the associated
dlIndex_ItemDataBound event handler executes. This event handler ensures that we are working with an
Item or AlternatingItem, and then programmatically references the HyperLink Web control in the ItemTemplate.
Finally, the event handler sets the Text property of the HyperLink control to the name of the image and
its filesize in kilobytes, and sets the NavigateUrl property such that the N querystring
value equals the current index of the image in the array. This allows the user to jump to a particular image in
the slideshow.
Conclusion
In this article we looked at an ASP.NET Web page that could be dropped into a directory of images to display those images
as a slideshow. In fact, you can see a live demo of Default.aspx, which contains
some pictures from London. In a future article I plan on making displaying a slideshow of images even easier. Specifically,
we'll look at how to convert Default.aspx into an HTTP handler. By doing this, you won't need to manually
copy over Default.aspx to each directory of images. Rather, you can simply send your visitors to some
non-existent URL, like /images/London/slideshow.ashx. We'll see how to accomplish this later!