Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

(Extended) Modal Window in Silverlight

0.00/5 (No votes)
2 Apr 2009 1  
An extension of the code submitted in the article: Modal Window in Silverlight. This extension wraps the hosted control in a window frame that provides various modal features.

Introduction

Knowm Ercy's article Modal Window in Silverlight provided a nice way to display a Silverlight UserControl in a way that looks and feels modal. Here at ProModel, Inc. we were interested in this functionality (which is not natively available within Silverlight at the moment) and its use in our Silverlight based applications. Using Knowm's article as a starting point, we put together an extension that "wraps" the hosted UserControl inside a window frame which provides for resizing, moving, maximizing, and many of the other features enjoyed with traditional modal Windows forms.

This code is presented "as is" and we are aware of a number of improvements that can and should be made. However, given our in-house time constraints and the lack of a similar modal solution out there (a free one anyway), we decided to make this source available for improvement by anyone who's up for the challenge.

Background

Although we've made some departures from the original architecture, it is basically as we found it, just extended, so reading Knowm Ercy's article Modal Window in Silverlight should prove helpful in understanding the code.

There are two classes that work to provide the basic modal display:

  • Modal

    A simple class containing the popup control which host the "modal" form and provides basic show/hide functionality.

  • ModalHost

    A class that hosts the UserControl which is to be displayed modally. This class renders a "background canvas" that covers the entire browser window and prevents interaction with anything other than the hosted control, giving the impression that the hosted control is modal. Also, the ModalHost class provides basic mouse drag functionality such that the hosted control can be moved if a mouse drag occurs on its surface.

Each of the two modal display classes contained in our library (ModalControl, WindowedModalControl) contain an instance of each of these class. In the case of ModalControl, the simple base classes are used (as with Knowm's provided project). In the case of WindowedModalControl, each class is derived to provide the extended functionality.

Here is a summary of the functionality provided in the derived classes:

  • WindowedModal (derived from Modal)

    All that is done in this child class is a simple override of a method that sets the ModalHost instance within the Modal class. This allows us to insert our custom ModalHost (WindowedModalHost).

    internal class WindowedModal : Modal
    {
    #region Method Declarations
    protected override void SetHost(IModal ctrl, bool useCanvasPainting)
    {
        _host = new WindowedModalHost(ctrl, useCanvasPainting);
    }
    #endregion
    }
  • WindowsModalHost (derived from ModalHost)

    This class overrides a few basic ModalHost behaviors/adds some simple functionality:

    1. Provides RestoreState property which keeps track of whether or not the WindowedModalControl is maximized.
    2. Overrides the CenterWindow() method so that it takes the RestoreState into account.
    3. Overrides mouse events to prevent the base class from taking any action.
    public override void CentreWindow()
    {
        double dblX = 0.0, dblY = 0.0;
        UserControl modal = _modal as UserControl;
        if (RestoreState == RestoreState.Unmaximized)
        {
            // width
            if (_modal != null && !double.IsNaN
    		(WindowHelpers.GetControlSize(modal).Width) &&
            !double.IsNaN(Application.Current.Host.Content.ActualWidth))
            {
            dblX = ((Application.Current.Host.Content.ActualWidth - 
    			WindowHelpers.GetControlSize(modal).Width) / 2);
            modal.SetValue(Canvas.LeftProperty, dblX);
            }
            // height
            if (_modal != null && !double.IsNaN
    		(WindowHelpers.GetControlSize(modal).Height) &&
            !double.IsNaN(Application.Current.Host.Content.ActualHeight))
            {
            dblY = ((Application.Current.Host.Content.ActualHeight - 
    			WindowHelpers.GetControlSize(modal).Height) / 2);
            modal.SetValue(Canvas.TopProperty, dblY);
        }    
    }
    protected override void OnMouseLeftButtonDown
    		(object sender, MouseButtonEventArgs e)
    {
        // prevent the base class from taking action
    }
    protected override void OnMouseMove(object sender, MouseEventArgs e)
    {
        // prevent the base class from taking action
    }

The WindowedModalControl class provides the major functional extensions to Known's original work. This includes:

  1. Managing the placement of the hosted UserControl inside of a window frame
  2. Support for Maximize/Restore
  3. Support for display of window as both resizing and non-resizing
  4. A title bar with image and auto-truncating text caption
  5. Built-in OK, Cancel, Apply button support
  6. Auto-sizing of the hosted UserControl
  7. Usage of custom brushes for form header, background and text

Using the Code

Simply hosting your UserControl within the WindowedModalControl will look like this:

public void ShowWindowedModal(DialogClose callback, Panel panel)
{
     bool useCanvasPainting = true; 	// whether of not the non-modal space 
				// is darkened partially
     WindowedModalControl wmc = new WindowedModalControl
				(callback, MsgBoxButtons.OKCancelApply);
     TestUserControl tc = new TestUserControl();
     wmc.HostedControl = tc;
     wmc.ShowModal(panel, useCanvasPainting);
} 

This sample makes use of some of the more advanced features:

public void ShowWindowedModal(DialogClose callback, Panel panel)
{
    bool useCanvasPainting = true; 	// whether of not the non-modal space 
				// is darkened partially
    WindowedModalControl wmc = new WindowedModalControl
				(callback, MsgBoxButtons.OKCancelApply);
    TestUserControl tc = new TestUserControl();
    wmc.TitleBarBrush = Resources["ModalHeaderBrush1"] as Brush;
    wmc.FormBackgroundBrush = Resources["ModalBrush1"] as Brush;
    wmc.TitleImage = _titleImage;
    wmc.HostedControl = tc;
    wmc.ShowModal(panel, useCanvasPainting);
    wmc.AllowResizing = true;
    wmc.AllowMaximize = true;
    wmc.TitleBarText = "It's a Working Title...and it truncates if need be";
}

The provided source comes with a demo application that has source code samples alongside run-time examples. A compiled help file is also included.

Special Thanks

To Knowm Ercy for the work he put into his article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here