At 6Wunderkinder we are creating the Windows Store Version (WinRT) of Wunderlist. Our app basically has two kinds of pages. One is where you are logged in and one is where you are not logged in. We use a master page to take care of backgrounds and other stuff that is shared across pages. When all pages are the same, you just replace Window.Current.Content as Frame
(in App.xaml.cs
) with your master page (as described by Fons Sonnemans) and load all other pages within that masterpage. But what if you want to support multiple masterpages?
Well, it turns out it is very easy to do this and you can even use the default Frame from App.xaml.cs
Download a demo project or follow the next steps to create Application Navigation where pages can use a specific masterpage or no masterpage at all!
MasterPage.xaml
that acts as a masterpage. You can include some app-wide xaml like this:<Page
x:Class="MasterPageTest.MasterPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#FF363333">
<Grid.RowDefinitions>
<RowDefinition Height="43*"/>
<RowDefinition Height="213*"/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Master!" VerticalAlignment="Center" FontSize="48" Margin="100,0,0,0"/>
<TextBox HorizontalAlignment="Center" x:Name="search" TextWrapping="Wrap" Text="TextBlock1" VerticalAlignment="Center" FontSize="18.667" Width="200"/>
<Frame x:Name="ContentFrame" Content="Frame" Grid.Row="1" Margin="100"/>
<StackPanel Margin="0,0,100,0" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="MainPage" Click="ButtonBase_OnClick1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
<Button Content="Second Page" Click="ButtonBase_OnClick2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
<Button Content="Logout" Click="ButtonBase_OnClick3" HorizontalAlignment="Center" VerticalAlignment="Center" Width="150" Height="80" Margin="0"/>
</StackPanel>
</Grid>
</Page>
Don’t worry about the Button Click Handlers. We will implement them later. Important in the code above is the placeholder for your content:
<Frame x:Name="ContentFrame" Content="Frame" Grid.Row="1" Margin="100"/>
NavigateService.cs
to your project and enter this code:public class NavigateService {
private static readonly Lazy<NavigateService> lazy = new Lazy<NavigateService>(() => new NavigateService());
public static NavigateService Instance { get { return lazy.Value; } }
public Frame Frame { get; set; }
public void Navigate(Type pageType) {
Frame.Navigate(pageType);
}
public void Navigate(Type pageType, Type masterPageType) {
var masterPage = Frame.Content as Page;
if (masterPage != null && masterPage.GetType() != masterPageType) {
Frame.Navigate(masterPageType);
masterPage = Frame.Content as Page;
}
var contentFrame = masterPage.FindName("ContentFrame") as Frame;
contentFrame.Navigate(pageType);
}
}
App.xaml.cs
and the OnLaunched method with:protected override void OnLaunched(LaunchActivatedEventArgs e) {
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null) {
rootFrame = new Frame();
Window.Current.Content = rootFrame;
}
NavigateService.Instance.Frame = rootFrame;
if (rootFrame.Content == null) {
rootFrame.Navigate(typeof(LoginPage), e.Arguments);
}
Window.Current.Activate();
}
Masterpage.xaml.cs
and add the following handlers:private void ButtonBase_OnClick1(object sender, RoutedEventArgs e) {
NavigateService.Instance.Navigate(typeof(MainPage), typeof(MasterPage));
}
private void ButtonBase_OnClick2(object sender, RoutedEventArgs e) {
NavigateService.Instance.Navigate(typeof(SecondPage), typeof(MasterPage));
}
private void ButtonBase_OnClick3(object sender, RoutedEventArgs e) {
NavigateService.Instance.Navigate(typeof(LoginPage));
}
You will get some errors because you don’t have a SecondPage.xaml
and LoginPage.xaml
yet.
SecondPage.xaml
and put a page title on it so you will recognize it once loaded in the masterpage.MainPage.xaml
and put a title on that as wellLogin.xaml
and enter the following XAML:<Grid>
<Button Content="Login" Click="ButtonBase_OnClick" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="100"/>
</Grid>
LoginPage.xaml.cs
and add the following handler:private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
NavigateService.Instance.Navigate(typeof(MainPage), typeof(MasterPage));
}
Now run your code and you will see that the Login page uses no masterpage and the other pages share Masterpage.xaml
.
This is a very basic masterpage navigation system. For our app we extended it with viewmodel injection. If you need help with that, just email me (info@loekvandenouweland.com)!