#wp7dev Silverlight Page Base Class — Why and How

Any time I am told “copy & paste [anything]” in more than one place, I start looking for alternatives.  So it was when I was following this guide to adding page transitions to DataHub.

20 lines of XAML for each of 40 XAML files.  Luckily I identified this early on and came up with a clean solution:  Each of my PhoneApplicationPages would inherit from a single class, which I called BasePage.

namespace DataHub
{
    public class BasePage : PhoneApplicationPage
    {
        public BasePage()
        {
            NavigationInTransition navInTransition = new NavigationInTransition();
            navInTransition.Backward = new SlideTransition { Mode = SlideTransitionMode.SlideDownFadeIn };
            navInTransition.Forward = new SlideTransition { Mode = SlideTransitionMode.SlideUpFadeIn };
            NavigationOutTransition navOutTransition = new NavigationOutTransition();
            navOutTransition.Backward = new SlideTransition { Mode = SlideTransitionMode.SlideDownFadeOut };
            navOutTransition.Forward = new SlideTransition { Mode = SlideTransitionMode.SlideUpFadeOut };
            TransitionService.SetNavigationInTransition(this, navInTransition);
            TransitionService.SetNavigationOutTransition(this, navOutTransition);

            this.SetValue(TiltEffect.IsTiltEnabledProperty, true);

        }

along with these changes to the start & end XAML tags for each page:

<dh:BasePage
xmlns:dh="clr-namespace:DataHub">

...

</dh:BasePage>

Much cleaner! With this bit of infrastructure worked out, I could move on to the real heart of the app.

Little did I know how useful this BasePage would be further down the line. So much so, I think I’ll have one in all future projects even if it’s initally blank.

A new problem arose when I was impementing better-together-dynamicorientationchanges-and-transitionframe. I noticed that if my device was held landscape and then the page was navigated, both the transition and the orientation change animations were playing. This was a pretty jarring user experience, and obviously in this case I wanted the transition animation only.

I had a twitter conversation with @DavidAns who replied “Avoiding it’d require specific (tricky?) changes”.

Luckily, I already had BasePage in place, so the changes were not so tricky:


 protected static HybridOrientationChangesFrame MyHybridOrientationChangesFrame
        {
            get { return (HybridOrientationChangesFrame)(((App)(App.Current)).RootFrame); }
        }

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            MyHybridOrientationChangesFrame.IsAnimationEnabled = false;
        }

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
                UIHelper.SetTimeout(300, () =>
                {
                    MyHybridOrientationChangesFrame.IsAnimationEnabled = true;
                });
            }
        }

Another use for BasePage appeared when Aaron, our UX designer, decided to include a “home” button on every DataHub page. Not wanting to include a circular reference (*ahem* AMAZON *ahem*) and specifically WANTING the page transitions between the starting point and home, I let BasePage do some automatic “back” navigation when a MainViewModel property was set.

void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (!IsCurrentPage) return;
            if (!IsMainPage)
            {
                if (e.PropertyName == "GoHome")
                {
                    if (App.ViewModel.GoHome)
                    {
                        UIHelper.SetTimeout(100, () =>
                        {
                            this.NavigationService.GoBack();
                        });
                    }
                }
            }
        }

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            MyHybridOrientationChangesFrame.IsAnimationEnabled = false;
            IsCurrentPage = false;
            App.ViewModel.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(ViewModel_PropertyChanged);
        }

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            App.ViewModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(ViewModel_PropertyChanged);
            IsCurrentPage = true;

            if (App.ViewModel.GoHome)
            {
                if (IsMainPage)
                {
                    App.ViewModel.GoHome = false;
                    UIHelper.SetTimeout(300, () =>
                    {
                        MyHybridOrientationChangesFrame.IsAnimationEnabled = true;
                    });
                }
                else
                {
                    UIHelper.SetTimeout(300, () =>
                    {
                        this.NavigationService.GoBack();
                    });
                }
            }
            else
            {
                UIHelper.SetTimeout(300, () =>
                {
                    MyHybridOrientationChangesFrame.IsAnimationEnabled = true;
                });

            }

        }

This did require some careful coding any time a page needed to make use of OnNavigatedTo directly.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if (App.ViewModel.GoHome) return;

...

}

A final use for BasePage just came up for DataHub now that we are working on the Silverlight-based “desktop” version. I am sharing (linking) as much of the code between projects as possible, including the code-behind for the XAML files. BasePage is implemented as project-specific, handing all plumbing differences (and inheriting from System.Windows.Controls.Page instead of Microsoft.Phone.Controls.PhoneApplicationPage). More on this in a future blog post (if there is any interest…)

Regards,
Jason

This entry was posted in WP Dev Tips. Bookmark the permalink.

One Response to #wp7dev Silverlight Page Base Class — Why and How

  1. IAmJustAReader says:

    Thanks for sharing

Leave a Reply

Your email address will not be published. Required fields are marked *

*



You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>