5,117,952 members and growing! (13,454 online)
Email Password   helpLost your password?
Web Development » Silverlight » General     Intermediate License: The Microsoft Public License (Ms-PL)

Silverlight2 Lightbox

By Tim Mason

A Silverlight2 lightbox control
C# (C# 3.0, C#), JScript, .NET (.NET, .NET 3.5), Visual Studio (VS2008, VS), XAML, Design, Dev

Posted: 28 Apr 2008
Updated: 28 Apr 2008
Views: 3,828
Announcements



Search    
Advanced Search
Sitemap
4 votes for this Article.
Popularity: 2.67 Rating: 4.43 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
1 vote, 25.0%
4
3 votes, 75.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

TeamLive (the project I have been working on recently) blends Asp.net, Ajax and Silverlight in a number of places and I was interested to see how far I could push the html/Silverlight blend - the lightbox seemed like a good component for my experiment.

For those of you wondering, a Lightbox is an effect that fades the page in the background to show you new content in the foreground.

This article isn't intended to be a Silverlight tutorial, if you are new to this technology then I recommend reading some of the beginners tutorials before using this code.

Background

TeamLive blends Asp.net, Ajax and Silverlight in a number of places. E.g. during a multi-file upload we adjust the OBJECT's styles giving it more screen space for displaying the progress bars.

image

One of the controls I have been working on for the next iteration of TeamLive is a lightbox to help users navigate their image grids.

Some of the requirements for the lightbox:

  • Only load the big image if needed (duh!)
  • Small xap (the js lightboxes we've used in the past have required a lot of js and/or associated images) - this xap is only 8K
  • Only one Silverlight lightbox object per page (we didn't want lots of objects being created)
  • Simple to use (drop a xap on a page and call some js)
  • Degrade cleanly when Silverlight 2 is not present

Demo

If you have Silverlight 2 installed visit http://www.devprocess.com and click one of the images...

Back?

I hope you saw something like this:

image

If you just got an ugly window.open then you don't have Silverlight 2.

Using the Code

Firstly, the PageBlanket silverlight class. A simple class that can be used to disable the page with an overlay.

A similar technique is used by the modal popup overlay (see the ModalPopup on the AjaxControlToolkit: http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ModalPopup/ModalPopup.aspx)

/// <summary>
/// PageBlanket covers a page with a partially transparent div
/// to prevent users interacting with the page - can be used to simulate a modal
/// dialog
/// </summary>
public class PageBlanket
{
    HtmlElement _blanket = null;
    /// <summary>
    /// Lazy initialization on first call
    /// </summary>
    private void Initialize()
    {
        if (_blanket == null)
        {
            //create a div that will take up the whole page and cover the content underneath
            _blanket = HtmlPage.Document.CreateElement("div");

            HtmlPage.Document.Body.AppendChild(_blanket);
            _blanket.SetStyleAttribute("position", "fixed");
            _blanket.SetStyleAttribute("top", "0px");
            _blanket.SetStyleAttribute("left", "0px");
            _blanket.SetStyleAttribute("height", "100%");
            _blanket.SetStyleAttribute("width", "100%");
            _blanket.SetStyleAttribute("backgroundColor", "#808080");
            _blanket.SetStyleAttribute("filter", "alpha(opacity=50)");
            _blanket.SetStyleAttribute("opacity", "0.5");
            _blanket.SetStyleAttribute("z-index", "3");
            _blanket.SetStyleAttribute("display", "none");
        }
    }

    /// <summary>
    /// Show the blanket and cover the page
    /// </summary>
    public void Show()
    {
        //just in case not init'ed
        Initialize();
        //clear display attribute to show the blanket
        _blanket.SetStyleAttribute("display", "");
    }

    /// <summary>
    /// Hide the blanket again
    /// </summary>
    public void Hide()
    {
        //hide the blanket
        _blanket.SetStyleAttribute("display", "none");
    }
}

Page blanket creates a div, sets the style, jams it in the page, and toggles the display style to show/hide the div. This effectively disables the page while we do the Silverlight stuff.

Dynamically showing/hiding the Silverlight control turned out to be harder.

Firefox gets upset if you start moving the control around, changing zIndex, altering display style dynamically.

I was getting working code in IE7 and “Trying to get unsupported property on scriptable plugin object!” errors in Firefox.

The solution I found (works on IE7, Firefox2 and Safari (not tested on anything else yet)) was to set a small Width and Height (yeah, yeah - I know). I make sure I set the style of the object at the start (changing position and zIndex dynamically in the C# screwed up the scriptableobject):

The lightbox code

Note it positions the lightbox in the center of the screen. Originally the code positioned the lightbox over the item that launched it - but it never looked quite right so I tried centering the lightbox. I’m not sure it’s much better in the center - so I’m waiting for inspiration.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Windows.Media.Imaging;

namespace dpLightbox
{
    [ScriptableType]
    public partial class Page : UserControl
    {

        public Page()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(Page_Loaded);
            //keep the lightbox in the center if page is resized
            HtmlPage.Window.AttachEvent("onresize", new EventHandler(Window_Resize));
        }

        void Window_Resize(object sender, EventArgs e)
        {
            PositionToCenter();
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            //register for javascript control
            HtmlPage.RegisterScriptableObject("LightboxController", this);

            //the close button
            bClose.MouseEnter += new MouseEventHandler(bClose_MouseEnter);
            bClose.MouseLeave += new MouseEventHandler(bClose_MouseLeave);
            bClose.MouseLeftButtonUp += new MouseButtonEventHandler(bClose_MouseLeftButtonUp);
        }

        bool closing = false;
        /// <summary>
        /// Close the lightbox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void bClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            closing = true;
            rCloseGlow.Opacity = 0.0;
            sbLightbox.Completed += new EventHandler(sbLightbox_Completed);
            sbLightbox.AutoReverse = true;
            sbLightbox.Stop();
            sbLightbox.Begin();
            sbLightbox.Seek(new TimeSpan(0, 0, 0, 0, 500));

        }

        void sbLightbox_Completed(object sender, EventArgs e)
        {
            if (closing)
            {
                _blanket.Hide();

                Width = 0;
                Height = 0;
                HtmlPage.Plugin.SetStyleAttribute("width", "1px");
                HtmlPage.Plugin.SetStyleAttribute("height", "1px");
            }

            closing = false;
        }

        void bClose_MouseLeave(object sender, MouseEventArgs e)
        {
            rCloseGlow.Opacity = 0.0;

        }

        void bClose_MouseEnter(object sender, MouseEventArgs e)
        {
            rCloseGlow.Opacity = 1.0;
        }

        double paddingTop = 55;
        double padding = 25;
        PageBlanket _blanket = new PageBlanket();
        [ScriptableMember]
        public void showLightbox(string imgTitle, string imgSrc, double imgWidth, double imgHeight)
        {
            _blanket.Show();

            txtTitle.Text = imgTitle;
            imgMain.Source = new BitmapImage(new Uri(imgSrc, UriKind.RelativeOrAbsolute));
            imgMain.ImageFailed += new ExceptionRoutedEventHandler(imgMain_ImageFailed);

            //setup the lightbox size
            double dWidth = imgWidth + (padding * 2);
            double dHeight = imgHeight + (padding + paddingTop);

            Width = dWidth;
            Height = dHeight;

            kfWidth.Value = dWidth;
            kfHeight.Value = dHeight;

            HtmlPage.Plugin.SetStyleAttribute("height", Height.ToString() + "px");
            HtmlPage.Plugin.SetStyleAttribute("width", Width.ToString() + "px");

            sbLightbox.Stop();
            sbLightbox.Seek(new TimeSpan(0));
            sbLightbox.AutoReverse = false;
            sbLightbox.Begin();

            HtmlPage.Plugin.SetStyleAttribute("display", "");

            PositionToCenter();
        }

        void imgMain_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            //the developer needs to decide what should happen here
            //empty lightbox?  don't show the lightbox?

        }

        private void PositionToCenter()
        {
            Size clientBounds = BrowserHelper.GetClientBounds();
            Point ptScrollPos = BrowserHelper.GetScrollPosition();

            double dTop = ptScrollPos.Y + ((clientBounds.Height - Height) / 2);
            double dLeft = ptScrollPos.X + ((clientBounds.Width - Width) / 2);

            HtmlPage.Plugin.SetStyleAttribute("top", dTop.ToString() + "px");
            HtmlPage.Plugin.SetStyleAttribute("left", dLeft.ToString() + "px");
        }

    }

}

Using the lightbox

In your aspx:

<asp:Silverlight ID="slLb" runat="server" Source="~/ClientBin/dpLightbox.xap" Version="2.0" 
Width="1px" Height="1px" PluginBackground="Transparent" Windowless="true" 
style="position:absolute;z-index:4;">
    <PluginNotInstalledTemplate></PluginNotInstalledTemplate>
</asp:Silverlight>

The PluginNotInstalledTemplate gets rid of the install Silverlight 2 prompt when Silverlight 2 isn’t installed - which is nice as the Lightbox isn’t essential functionality.

Put this bit of Javascript in the head to simplify usage. This gets the Silverlight xap to show the lightbox or (shudder) a window.open if Silverlight 2 isn’t there.

<script type="text/javascript">
    function lightbox(imgTitle,imgSrc,imgWidth,imgHeight)
    {
        var lbContent=document.getElementById("slLb").Content;
        if(lbContent!=null)
        {
            lbContent.LightboxController.showLightbox(imgTitle,imgSrc,imgWidth,imgHeight);
        }
        else
        {
            window.open(imgSrc,"noSilverlight","menubar=no,toolbar=no,height="+imgHeight+",width="+imgWidth);
        }
    }   
</script>

Showing a lightbox - to show a lightbox call the function above.

<a href="javascript:lightbox('TeamLive designer',
    'http://www.devprocess.com/App_Themes/Default/lb_designer.jpg',600,296);">

<img src="App_Themes/default/designer.jpg" class="photosmall" 
    width="264" height="130" alt="Screenshot from devProcess TeamLive" />

</a>

TeamLive

You can keep up to date with any updates (I will also try to make them here) at our blog: TeamLive Blog

History

28 April 08, Article submitted

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

Tim Mason


Chief architect and project lead for many devProcess projects, including TeamLive.

http://www.TeamLive.com

Occupation: Architect
Company: Development Process Ltd.
Location: United Kingdom United Kingdom

Other popular Silverlight articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 3 of 3 (Total in Forum: 3) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralnicememberAbhijit Jana22:06 28 Apr '08  
GeneralLittle bugmemberRimas20:32 28 Apr '08  
GeneralRe: Little bugmemberTim Mason0:53 29 Apr '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 28 Apr 2008
Editor:
Copyright 2008 by Tim Mason
Everything else Copyright © CodeProject, 1999-2008
Web13 | Advertise on the Code Project