As my first real experiment in building a Silverlight control, I wanted to realize something that could permit me to offer to the users a windows-like experience application hosted in the browser, so I started wondering how difficult was to implement a control that could host other silverlight control and even pages, this control should then act as a 'real' window and can be dragged on the surface (over other controls) and with resizing and closing capabilities, plus I want to give the Window a look similar to WIndows Vista Aero Desktop windows.
To be honest Silverlight is very flexible and its templating capabilities made the task a lot simplier than I tought at start, here's what we want to obtain:
This 'tutorial' will be divided in a series of 3 articles that describe:
- the basic idea and the creation of the control.
- implementation of dragging capabilities.
- implementation of resizing capabilities.
The source code that comes with each part will however include the complete example solution (since I'm too lazy to divide it in parts), so let's get started.
There are a bunch of articles out there that describes how to create a user control and how to skin it so I won't dig deep in that; one of the best and very simple to follow is: 'Craft Custom Controls for SIlverlight 2' by Jeff Prosise (http://msdn.microsoft.com/en-us/magazine/cc721611.aspx), so use it as you main reference in creating your new controls.
Let's point out the ideas that are behind the Window control:
To move the windows around and resize them freely we need to use the 'Canvas trick' and place an outside Canvas that encapsulate any other controls on the page in which we want to use the windows, this is a must since I've not yet found a way to inject dinamically a canvas on a preexisting page.
We then need 2 classes basically: a Window class that will handle the windows features and a WindowManager class that act like a supervisor for all the windows hosted on the page, this is a very simple class that act like the operating system do with normal windows...it creates them and when he receive the WM_CLOSE message (placed in the message pump by the windows) it closes them.
We are forced to implement our own mecanics since silverlight do not offer any native way (yet) to handle windows like we want to do, we also do not have a message pump to use so we will use the notification events that will be raised by the Window.
The Windows control is quite simple to realize at start, its main template will be contained in the Generic.xaml file of the solution and will be automatically loaded for each instance since we specify the DefaultStyleKey property in the constructor of the class, the template will define some pure graphical controls and 4 named controls that will represent:
- the window surface itself - used for resizing the control
- the caption bar - used for dragging the window around
- the caption bar text
- the close button.
The style for the close button is defined in the App.xaml file and redefines the template of a normal silverlight button, you can use Expression Blend to take a look at both files and edit the templates.
We will get a reference to those control when the template will be loaded by the runtime (just before rendering it) in the overridden OnApplyTemplate() function: