
Figure 1 - Slide Show Control for ASP.NET
Introduction
So where do you think this garden picture is taken? California? Maine? Florida, maybe? Believe it or not its smack in the middle of Manhattan in a section called Alphabet City in a garden community called La Plaza Cultural. The garden not only has flowers and herbs, but features an apple tree, a pear tree, and a peach tree, just to name a few. Whoever said that Manhattan was just a cement jungle, obviously never wandered into La Plaza Cultural.
The picture in figure 1 is shown in my web browser to illustrate a quick web control I threw together to allow me to view a set of pictures in a directory through ASP.NET. The secret of this control is that upon pressing the Next or Previous Button, the ImageUrl in the page is dynamically changed and the page is redirected to itself to refresh the contents. The control works as follows:
1) All image filenames are read in from an image directory directly under the SlideShowControl Directory and each stored in a Session state variable
2) The index of the last file is also stored in a Session variable
3) Upon hitting Next, the index of the last file is incremented and the ImageUrl associated with the next index is assigned to the image control
4) The page is redirected back to itself to display the next image.
2) The index of the last file is also stored in a Session variable
3) Upon hitting Next, the index of the last file is incremented and the ImageUrl associated with the next index is assigned to the image control
4) The page is redirected back to itself to display the next image.
This article also illustrates how to embed a user control into another user control. You would think this would be easy, but it turns out to be trickier than if you were to do it in a windows form. Upon embedding one web user control into another, I started getting circular references and had to figure out a way to prevent one user controls reference from interfering with the other user controls reference. This involved removing additional references that were inserted by the visual studio designer into both ascx (user control) files and also inheriting one of the controls from an abstract base class instead of directly from System.Web.UI.UserControl. I also placed each user control in a separate web folder so the assemblies wouldn't step on each other. I'm still not sure if one of all of these techniques solved the problem in the end, but it would be nice if the problem actually didn't happen in the first place :-).
The two user controls created in the article are SlideShowControl and SlideShowControlContainer. The SlideShowControl deals with most of the functionality of the control pertaining to the image. The SlideShowControlContainer holds the SlideShowControl and the two buttons: Previous and Next. When the Previous or Next button is pressed, the previous and next functionality calls are propogated to the SlideShowControl.
Code
The heart of the code for the SlideShow resides in the SlideShowControl.ascx.cs file. Upon loading this control, the file paths are read into the session states and the initial image is drawn.
Listing 1 - Initial Page Load of the SlideShowControl
protected void Page_Load(object sender, EventArgs e){ if (IsPostBack == false) { // the the initial image URL imgCurrent.ImageUrl = GetImageUrl(); if (Session["CurrentImageIndex"] == null) { // read in all the image paths and store in session states IndexImages(); // Draw the image by assigning the image control to a new ImageUrl // and redirecting the page back to itself DrawImage(); } } } |
The image file names are initially read in using the GetFile method of the Directory class. In this case, all files with the jpg extension are read into the Session state hash. Each filename hash value has the key (imagedirectory + unique integer value). We can use this combined key whenever we want to get the next or previous image file to assign to our Image URL in the .NET Web Image Control.
Listing 2 - Reading in all the Image Files and Assigning them to the Session
private void IndexImages() {// determine the actual path of the asp.net application on the serverstring fullSitePath = this.Request.PhysicalApplicationPath; // extend the path to include our slide show control image directory string serverImageDirectory = fullSitePath + ConfigurationSettings.AppSettings["ImageDirectory"]; // save the path information in the Session State Session["FullImagePath"] = serverImageDirectory; // get all the files in the images directory with the desired extensionstring[] files = Directory.GetFiles(serverImageDirectory, String.Format("*.{0}", _imageExtension)); // store all the file names in the session state, keyed by // the directory name and a unique integer. int count = 0; Session["CurrentImageIndex"] = 0; Session["ImageDirectory"] = _imageDirectory;foreach (string file in files) { Session[_imageDirectory + count.ToString()] = file.Substring(file.LastIndexOfAny(new char[]{'/', '\\'}) + 1); count++; } // store the number of images in the session state Session["ImageCount"] = count; } |
Listing 3 - Dynamically changing the Image inside the Control
public void DrawImage() { // assign the image url using the current file name imgCurrent.ImageUrl = GetImageUrl(); // also assign the correct dimensions for the image Size imageDimensions = GetImageDimensions(); imgCurrent.Width = new Unit(imageDimensions.X); imgCurrent.Height = new Unit(imageDimensions.Y); // redirect back to the control's parent page string urlName = this.Request.Url.ToString(); this.Response.Redirect(urlName); } |
The GetImageDimensions constructs a bitmap from the path name of the current image file. Then it extracts the Width and Height from the image into a Size object and returns the size.
Listing 4 - Retrieving the Image URL and the Image Dimensions
private string GetImageUrl() { // use the pages ability to resolve the directory path into a browser readable URL return this.Page.ResolveClientUrl("~/" + _imageDirectory + "/" + GetCurrentFileName().ToString()); } /// <summary> /// Gets the image Width and Height from the actual bitmap/// </summary> /// <returns>size containing Width and Height of Image</returns>private Size GetImageDimensions() { // get the image path for the current file string currentImagePath = Session["FullImagePath"] + "\\" + GetCurrentFileName(); // put it in a bitmap Bitmap bmp = new Bitmap(currentImagePath); // use the bitmap class to get the dimensions of the bitmap Size result = new Size(bmp.Width, bmp.Height); // clean up the memory bmp.Dispose(); // return the dimensions return result; } |
The previous and next click events are captured in the SlideShowControlContainer web user control. This control is the parent of the SlideShowControl web user control. The code for this control is shown in listing 5. Upon pressing a button in the browser, the SlideShowControlContainer calls the Next_Click or Previous_Click methods of the SlideShowControl.
Listing 5 - Methods in the SlideShowControlContainer User Control for handling the Previous and Next Buttons
public partial class SlideShowControlContainer : System.Web.UI.UserControl { protected void Page_Load(object sender, EventArgs e) { if (IsPostBack == false) { // Handle control logic for enabling and disabling the previous and next button when we have redirected back to the parent page btnPrevious.Enabled = (bool)Session["PreviousButtonEnabled"]; btnNext.Enabled = (bool)Session["NextButtonEnabled"]; } }protected void btnPrevious_Click(object sender, EventArgs e) { // handle the previous click button SlideShowControl1.Previous_Click(sender, e); } protected void btnNext_Click(object sender, EventArgs e) { // handle the next click button SlideShowControl1.Next_Click(sender, e); } } |
Listing 6 - Methods in the SlideShowControl for Handling Changing the Image upon a Button Press
public void Previous_Click(object sender, EventArgs e) { // go to the previous image DecrementCurrentImageIndex(); DrawImage(); }public void Next_Click(object sender, EventArgs e) { // go to the next image IncrementCurrentImageIndex(); DrawImage(); } |
Listing 7 - Incrementing the Current Image Index
public void IncrementCurrentImageIndex() { // previous button automatically enabled when next button is pressed Session["PreviousButtonEnabled"] = true; // if we have not reached the last picture, // increment the current image index in the session if (((int)Session["CurrentImageIndex"]) < ((int)Session["ImageCount"] - 1)) { Session["CurrentImageIndex"] = (int)Session["CurrentImageIndex"] + 1; } // Set the next button enabled state based upon the current image index Session["NextButtonEnabled"] = ((int)Session["CurrentImageIndex"] < ((int)Session["ImageCount"] - 1)); } |
The great thing about ASP.NET helps you go beyond HTML to create highly functional web controls to greatly enhance the web users experience no matter what browser they are using. With ASP.NET, you can dynamically alter images and text on the fly. The SlideShowControl is a useful exercise in .NET for understanding how to change images dynamically on the web. The next time you have a load of images you want to show to your friends, don' t let it slide, let them view the pictures all in one place with a little help from C# and ASP.NET.
0 comments:
Post a Comment