This blog post looks at the problem of showing modal dialog windows in applications that target both the Silverlight and WPF platforms. A solution is provided which allows modal dialogs to be written that work well for both technologies.
Silverlight is, roughly speaking, a subset of Windows Presentation Foundation (WPF). This means that it is possible to write applications that target both frameworks, allowing you to develop applications that work both on the desktop and on the web using the same codebase.
However, Silverlight is not a strict subset of WPF, the differences between the two frameworks can be summed up as follows:
- Things that WPF has that Silverlight does not
- Things that Silverlight has that WPF has not
- Things that both framework have but are different!
There are a great many things that the WPF framework has that Silverlight does not, mostly due to the size constraints of Silverlight being a browser plugin (1). There are a few things that Silverlight has, such as Out Of Browser (OOB) support and local storage which are not in WPF because they relate to the browser context (2). If these areas are avoided, the creation of a cross-platform application can be straightforward, however it is point (3) that causes problems.
When developing an application which targets both frameworks it makes sense to do most of your development primarily in Silverlight in order to avoid accidentally using WPF features. In practical terms the way most people achieve this is to create two projects, one Silverlight, one WPF. The WPF project will include links to the files within the Silverlight project (This is achieved by selecting "Add existing item ...", then selecting the "Add as link" option). The following diagram highlights the linked files in the attached project:
The first obstacle to overcome is the entry point into the application. Silverlight applications render a single
UserControl as the
RootVisual of the instantiated application, wheres WPF applications will create a
Window instance when launched. This problem is easily solved by simply hosting the
UserControl, which is the starting point for the Silverlight application, within a
With this small obstacle cleared, you can create some pretty decent cross-framework applications (as long as you avoid the temptation of looking at all the WPF controls you are missing out on!).
I have created quite a few WPF / Silverlight applications in this manner, and the process, although a little clunky (I usually have two Visual Studio instances open so that I can keep the two versions in synch), works pretty well. However, the next major obstacle I experienced is that of creating a modal dialog. This falls firmly into category (3).
Modal dialog functionality was added in Silverlight 3. To pop-up a modal dialog, create a page which inherits from
ChildWindow (rather than the usual
UserControl). This class provides a
Show method which pops up the dialog, and a
Closed event which is raised when the user hits the OK or Cancel. For example, you might create an error dialog and use it as follows:
Visual Studio has a template for the creating of modal dialogs via
However, with WPF things are a bit different. Whilst Silverlight modal dialogs are constrained to live within the Silverlight container on your web page, WPF dialogs are proper windows that you can move around your desktop (Interestingly, someone on stackoverflow has emulated Silverlight's ChildWindow in WPF, although I am not convinced that this will look right on a desktop application). Visual Studio does not have a template for creating modal dialogs in WPF, however, there is more than enough documentation regarding the various types of dialog on MSDN.
With WPF a
Window can be shown as modal as follows:
There are a few differences here, firstly
Window has a
Show method just like Silverlight's
ChildWindow, however, this will result in showing a modeless window. Instead we invoke the
ShowDialog method which shows a modal dialog, but there is another subtle difference, whilst
ChildWindow.Show returns immediately, with an event handler required to capture the modal dialog being closed, WPF's
Window.ShowDialog blocks until the dialog is closed.
So ... each framework has different classes for modal dialogs, and different interfaces for each. How do we resolve these differences?
Early in this blog post we saw how the
UserControl which is the entry point into our Silverlight application can be hosted in a WPF
Window. The same approach can be used for modal dialogs. We can create our modal dialog as a
With the above control hosted in a
Window depending on the platform. The problem is, we cannot explicitly make reference to either of these types in our common code (i.e. the code shared by WPF / Silverlight via file linking). This problem can be solved by employing the Gang of Four Adapter pattern.
We define an interface that gives the functionality that we require for hosting our
UserControl as a modal dialog:
Within the Silverlight project we create a concrete implementation of this interface based on
With the interface implemented in code-behind as follows:
Within WPF we have a similar implementation based on
Note that with WPF we have a few extra configuration options to consider, such as the
ShowInTaskbar property. The code-behind again implements our adapter interface:
So, within each project we have a framework specific implementation of this host. This allows us to create modal dialogs from the common / core code as follows:
Here is a Silverlight application with a dialog implemented using this hosting concept:
And here is a screenshot of the equivalent WPF application, where you can see the modal dialog is popped up as a window:
(You can download the sourcecode below if you want to have a go with the WPF app)
One final note ... I have deliberately steered clear of the whole patterns business in this blog post. As you are probably aware, the Model-View-ViewModel (MVVM) pattern is very popular within Silverlight and WPF, and often other patterns such as Service Locator and Dependency Injection are thrown into the mix. However, the community has been struggling a little with how best to model modal dialog behaviours from within an MVVM ViewModel. Interestingly a couple of developers have supplied solutions on codeproject and personal blogs, both faced questions and even criticisms that their approaches were not correct and unit testable (one of the central tenets of MVVM) and quickly followed up with articles demonstrating that you could in fact unit test their code (published here and here)
Whilst the use of a pattern such as MVVM which enforces a strong separation of application logic from the view will certainly help to solve problems such as WPF / Silverlight framework differences, in this particular instance I wanted to show a simple technical solution rather than walk into the awaiting patterns minefield!
You can download the full sourcecode for this article here: ModalDialogDemo.zip
Regards, Colin E.