Silverlight 2 represents a giant leap forward for developers of Rich Internet Applications (RIAs); the ability for .NET developers to leverage their programming skills in the wide variety of languages supported by the .NET framework permits for a wide degree of flexibility in application development. However, as with all new techniques there are shortcomings and areas that need extra work from developers. One area within Silverlight 2 that falls into this category is page switching.
Jesse Liberty has a great two part tutorial on switching pages effectively in Silverlight: Part 1, Part 2. However, this method has a rather serious design flaw: it fails to reuse the interface when switching. This means that if I have two pages with the same interface, I am essentially recreating the interface for each page. While I can certainly encapsulate static portions in user controls, the fact remains that I am still reloading these each time.
Building on Jesse’s tutorial I took things one step further and allowed the user to Switch pages in content area similar to how things are handled with ASP .NET Master Pages. This technique combines the effectiveness of Jesse’s switching method with a more modular design. This technique, however, pales in comparison to the flexibility offered in the Silverlight 3 Navigation Framework, which should be used exclusively once available.
To begin you will at least four pages, as shown below:
In this case we are using Page.xaml as the main page that will host the others, thus we define a new instance of Page.xaml as the RootVisual in App.xaml.cs. The Page.xaml XAML markup looks like this:
Notice the two areas I have marked:
1: xmlns:local="clr-namespace:TransitionApplication"2:3: <local:Switcher x:Name="Switcher" Height="110" Width="300"4: HorizontalAlignment="Center" VerticalAlignment="Center" />In this code we are simply creating a reference back to our application and including a user control called Switcher into the application markup. The code for switcher is rather unique as it does not contain any markup, this is intentional. Basically we will use Switcher to load other pages into the given content area. The code-behind for Switcher looks like such:
1: public partial class Switcher : UserControl2: {
3: public Switcher()4: {
5: InitializeComponent();
6:
7: if (Content == null)8: {
9: Content = new Page1();10: }
11: }
12:
13: public void Navigate(UserControl ucControl)14: {
15: Content = ucControl;
16: }
17: }
The purpose of this code is to provide a means for the parent page to navigate to new pages via the Navigate method. By default we will load Page1 into the application when it is first started.
From this point, our event handlers in the main page will suffice to perform the switch, an example is provided below, this is from Page.xaml.cs:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }1: public partial class Page : UserControl2: {
3: public Page()4: {
5: InitializeComponent();
6: }
7:
8: private void Button1_Click(object sender, RoutedEventArgs e)9: {
10: Switcher.Navigate(new Page1());11: }
12:
13: private void Button2_Click(object sender, RoutedEventArgs e)14: {
15: Switcher.Navigate(new Page2());16: }
17: }
This is pretty simple, each button set the Content of the Switcher to the respective page. Of course this is a simple example, but you can get an idea of how this could could work in a larger application.
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }