次の方法で共有


Creating a Custom Base Page for Windows Phone 7

When I first starting creating applications for Windows Phone 7, I noticed there was certain functionality that I was duplicating across my pages.  Just like I do with ASP.Net applications, my immediate thought was to create a custom base page, derived from PhoneApplicationPage, that all my pages would then inherit from.  Being fairly new to Windows Phone 7 development, and Silverlight development in general, it wasn’t readily apparent to me how to do this, but it turns out to be fairly straightforward.

To begin with I’ll obviously need a new base class similar to that shown below.

 With the BasePage class in place, we can then derive our individual pages from this class, similar to the following code for MainPage:

    1: public partial class MainPage : BasePage
    2: {
    3:     // Constructor
    4:     public MainPage()
    5:     {
    6:         InitializeComponent();
    7:     }
    8: }

In order to make this work, we also need to update the corresponding XAML file to reference the new base class.  This requires that we import our local namespace as well.  Line 9 in the next code snippet shows the namespace reference while lines 1 and 19 show the open/close tag used to reference the new BasePage class.

    1: <local:BasePage 
    2:     x:Class="Wp7CustomBasePage.Views.MainPage"
    3:     xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    4:     xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    5:     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    6:     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    7:     xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    8:     xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    9:     xmlns:local="clr-namespace:Wp7CustomBasePage.Views"
   10:     mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
   11:     FontFamily="{StaticResource PhoneFontFamilyNormal}"
   12:     FontSize="{StaticResource PhoneFontSizeNormal}"
   13:     Foreground="{StaticResource PhoneForegroundBrush}"
   14:     SupportedOrientations="Portrait" Orientation="Portrait"
   15:     shell:SystemTray.IsVisible="True">
   16:  
   17:     <!-- Content of page omitted for clarity -->
   18:  
   19: </local:BasePage>

That’s effectively all there is to it.

So what kind of functionality would you want in your base page?  I find that I typically add functionality related to navigation, messaging and state management.  When I refer to messaging I’m referring to the concept of sending notifications from the ViewModel back to the View.  This of course assumes that you are using MVVM in your applications.  Messaging isn’t directly supported in Silverlight for Windows Phone so I use the MVVM Light Toolkit for this purpose.  If you’re new to MVVM John Papa has a post that provides a good overview. 

So here’s the base page after some of this functionality has been added.

    1: public class BasePage : PhoneApplicationPage
    2: {
    3:     // Override OnNavigatedTo to register for messages from view model
    4:     protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    5:     {
    6:         base.OnNavigatedTo(e);
    7:         Messenger.Default.Register<string>(this, this.HandleMessage);
    8:     }
    9:  
   10:     // Override OnNavigatedFrom to unregister for messages from view model
   11:     protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
   12:     {
   13:         base.OnNavigatedFrom(e);
   14:         Messenger.Default.Unregister(this);
   15:     }
   16:  
   17:     // Correctly cast derived Application class for accessing public variables
   18:     public Wp7CustomBasePage.App MyApp
   19:     {
   20:         get { return (Wp7CustomBasePage.App)App.Current; }
   21:     }
   22:  
   23:     // Handler to display messages sent from ViewModel
   24:     private void HandleMessage(string message)
   25:     {
   26:         MessageBox.Show(message, "CAPTION", MessageBoxButton.OK);
   27:     }
   28:  
   29:     // Navigate to a specific view
   30:     protected void NavigateToView(string viewName)
   31:     {
   32:         NavigationService.Navigate(new Uri(String.Format("/Views/{0}.xaml", viewName), UriKind.Relative));
   33:     }
   34: }

With respect to the messaging discussion above, you’ll notice this is handled in the OnNavigatedTo and OnNavigatedFrom overrides in BasePage.  In OnNavigatedTo the page registers to receive messages from the ViewModel and passes a common handler for processing the message.  In this case, the handler displays a MessageBox.  Similarly, every time the user navigates away from the page it unregisters in theOnNavigatedFrom method.  Unregistering as you navigate away from the page avoids the problem of getting multiple messages if you had multiple pages instantiated that were simultaneously registered.  Now when any of my ViewModels send a message using code similar to the following:

    1: Messenger.Default.Send<string>("Work Done in Page 1 View Model.");

Any of my pages will automatically display a message box showing the message.

The final sample code is included below. (Requires the Windows Phone Developer Tools and MVVM Light Toolkit)

Wp7CustomBasePage.zip

Comments

  • Anonymous
    November 13, 2011
    The application bar throws an error: Error 16 The attachable property 'ApplicationBar' was not found in type 'PhoneApplicationPage'. Wp7CustomBasePageViewsMainPage.xaml 38 6 Wp7CustomBasePage Any idea how to overcome it? Thanks, Slobo

  • Anonymous
    February 19, 2012
    Good work ,thank you~

  • Anonymous
    April 05, 2013
    I'm getting a "The name "BasePage" does not exist in the namespace "clr-namespace:Wp7CustomBasePage.Views"" Error. Is there an updated version of this solution? Thanks.

  • Anonymous
    October 15, 2013
    This helped me, thank you!