Skip to main content
Email Password   helpLost your password?

Screenshot - Page1.png

Introduction

One of the really great enhancements in ASP.NET was the introduction of master pages. They help developers to create a consistent layout for the pages in an application. Unfortunately there is no such concept in WPF and XAML. In the following sample, I would like to show a simple way to build a control in WPF similar to an ASP.NET master page.

Building Master Pages in WPF

My application consists of a Window, which contains a menu and a frame, and three Pages. These pages will be displayed in the frame when a user clicks on the menu.

When I add a new page to my project I can add controls to this page and arrange them the way I like. In my sample I use a Grid to arrange a title and a description on my new page.

<Page x:Class="MasterPages.Page.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1"
    >
    <Grid Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

       <TextBlock Style="{StaticResource Title}" Grid.Column="0" 
                Grid.Row="0" Text="Page 1" />
       <TextBlock Grid.Column="0" Grid.Row="1" 
                Text="This is the content of Page 1." />
    </Grid>
</Page>

If I want to add a second page with a similar layout to my project without master pages, I would have to repeat the whole code for the grid to arrange title and description on my new page.

An easy way to encapsulate the grid layout is to build a user control for the general layout of a page. Therefore I add a new UserControl to my project. In the codebehind file of my control, I add two dependency properties, one for the title and one for the page content:

public partial class Master : System.Windows.Controls.UserControl
{
    public Master()
    {
        InitializeComponent();
    }

    // Title

    public object Title
    {
        get
        {
            return (object)GetValue(TitleProperty);
        }
        set
        {
            SetValue(TitleProperty, value);
        }
    }

    public static readonly DependencyProperty TitleProperty = 
    DependencyProperty.Register(
        "Title",
        typeof(object),
        typeof(Master),
        new UIPropertyMetadata());

    // PageContent

    public object PageContent
    {
        get
        {
            return (object)GetValue(PageContentProperty);
        }
        set
        {
            SetValue(PageContentProperty, value);
        }
    }

    public static readonly DependencyProperty PageContentProperty = 
    DependencyProperty.Register(
        "PageContent",
        typeof(object),
        typeof(Master),
        new UIPropertyMetadata());
}

Title and PageContent act as a placeholder. In the XAML file of my user control, I can arrange these placeholders:

<UserControl x:Class="MasterPages.App_Master.Master"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:MasterPages.App_Master">
    <Grid Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <ContentControl
            Grid.Column="0"
            Grid.Row="0"
            Style="{StaticResource Title}"
            Margin="0 0 0 10"
            Content="{Binding RelativeSource=
        {RelativeSource Mode=FindAncestor, 
        AncestorType={x:Type m:Master}}, Path=Title}" />


        <ContentControl
            Grid.Column="0"
            Grid.Row="1"
            Content="{Binding RelativeSource=
        {RelativeSource Mode=FindAncestor, 
        AncestorType={x:Type m:Master}}, Path=PageContent}" />
    </Grid>
</UserControl>

Now I can use my user control to build pages with a title and a content area. Therefore I have to include the namespace of the user control in the page. Then I can add the user control to the page as the root element. Within the user control I can specify a Title and a PageContent element in XAML. Title and PageContent can contain any other WPF elements:

<Page x:Class="MasterPages.Page.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:MasterPages.App_Master"
    Title="Page1">
    <m:Master>
        <m:Master.Title>
            Page 1
        </m:Master.Title>
        <m:Master.PageContent>
            This is the content of Page 1.
        </m:Master.PageContent>
    </m:Master>
</Page>

Page1 is now a lot easier to build. I do not have to remember for every page that I have to use a Grid with a margin of ten and other details. I simply can set the content for the properties Title and PageContent.

But it is not only possible to add text to the placeholder properties but also to add other WPF controls. In Page2 I add a StackPanel with further controls to the PageContent property:

<Page x:Class="MasterPages.Page.Page2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:m="clr-namespace:MasterPages.App_Master"
    Title="Page2">
    <m:Master>
        <m:Master.Title>
            Page 2
        </m:Master.Title>
        <m:Master.PageContent>
            <StackPanel>
                <TextBlock Text="Page 2 contains additional elements." />
                <ListBox>
                    <ListBoxItem>Item 1</ListBoxItem>
                    <ListBoxItem>Item 2</ListBoxItem>
                    <ListBoxItem>Item 3</ListBoxItem>
                </ListBox>
            </StackPanel>
        </m:Master.PageContent>
    </m:Master>
</Page>

Screenshot - Page2.png

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralNot able to name the controls add in PageContent Pin
Bolla Veera
4:24 11 Sep '07  
QuestionHow can i set the Name for childs Pin
eclere
0:42 15 Aug '07  
GeneralFine Pin
Marek Istvanek
21:04 10 Jul '07  
GeneralWell done Pin
Uwe Keim
19:50 8 Jul '07  
GeneralThanks. I voted it. Pin
Michael Sync
16:38 8 Jul '07  


Last Updated 8 Jul 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009