Introduction
Going back and forth between desktop and web apps development, and thinking some good pattern can be reused. Here is an example on how to implement the ASP.net master page pattern in WPF.
Background
The sample presented here is implemented with Visual Studio 2013 Express for Windows Desktop, .NET Framework 4.5. But the code can be reused with former versions of the framework.
Using the code
The sample shows a simple application with a tabbed UI. Actually two tabs are present, each with its own view.
Each view is supposed to have a title with a specific style, and some space on the left hand of the tab.
Rather than having to manually add a grid with at least two rows, two lines, and a title, each time a new view is started, I propose one way to implement a master page like solution.
- First, use a common base class for all views, this will allow for some factoring of common code. In our case the base view will hold a property storing the title string. Even though I have used this possibility, one could also want to use attached properties, but this is not covered here.
- Then define a global style targeting the base view and override the graphical tree in order to implement our suggested layout.
The base view
This is a simple C# class deriving from UserControl, it holds a dependency property storing the title of the view.
Using the base view
- For each view, have the class in the code behind derive from the base view
- In the XAML file for the view, add the namespace for the base view. For example :
xmlns:v="clr-namespace:MasterPage.View"
Then modify the tag to the name of the base view class, prefixed by the namespace :
<v:BaseView xmlns:v="clr-namespace:MasterPage.View" ...
Define the global style
Now it is time to define the global style for setting up the layout. As we want the style to be global, we will store it in the App.xaml of the application. After having added the appropriate namespaces to the Application tag, here is the style:
<!---->
<Style x:Key="MasterControlStyle" TargetType="{x:Type v:BaseView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type v:BaseView}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{StaticResource ResourceKey=LeftColumnLength}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{StaticResource ResourceKey=TitleHeight}"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!---->
<Label
Grid.Column="1"
Content="{TemplateBinding ViewTitle}"
Style="{StaticResource ResourceKey=TitleStyle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<!---->
<ContentControl Grid.Column="1" Grid.Row="1"
Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
We can see at the first line of the style it targets the base view and defines a control template with a grid. The grid has two rows and two columns. The first row is used to show the title, bound to the ViewTitle
property located in the base view. The first column is left empty, to provide for space. Finally, the cell located in the second column, of the second row will be the placeholder for the view.
Use the global style
From now on, our views all derive from the base view, and we have defined a global style whose aim is to override the layout of our views. One last step is required. We need to set the style for each view, for example :
<v:BaseView
x:Class="MasterPage.View.View1"
xmlns:v="clr-namespace:MasterPage.View"
ViewTitle="View 1 Title!!"
Style="{StaticResource MasterControlStyle}"
...
This will also be a good place to define the ViewTitle
property.
Screen captures
Here are two screen capture showing the two views
for the uploaded sample code (in Masterpage.zip):
History