Continuing our previous explorations of the TransitioningContentControl (hereand here – all WinPhone content here), we will now take a look at how we can extend the TCC to allow transitions to be defined on a per-page basis. Put simply, we would like to be able to have a default transition for all pages, and then provide a list of custom transitions that will be used on a page-by-page basis. You can also watch a screencast making these changes. Source is linked at the end of the article.
Our first step is to create a simple class that will be used to hold Page-to-Transition mappings. That class is shown below:
-
namespace System.Windows.Controls
-
{
-
public class PageTransitionMapping
-
{
-
public string Page { get; set; }
-
public string Transition { get; set; }
-
}
-
}
I added this class to the TCC folder from the previous screencast (download here). Notice that I changed the namespace to match the TCC’s namespace.
Next, the TCC is modified to allow us to provide Page-To-Transition mappings via the App.xaml file. See below:
public class TransitioningContentControl : ContentControl
{
private List
<PageTransitionMapping
> _mappings
= new List
<PageTransitionMapping
>(); public List<PageTransitionMapping> PageTransitionMappings { get { return _mappings; } }
…
The _mappings field stores a List<> of PageTransitionMapping objects. These mapping objects are created by accessing the PageTransitionMappings property via App.xaml as shown below
<phoneNavigation:PhoneApplicationFrame x:Name="RootFrame" Source="/MainPage.xaml">
<phoneNavigation:PhoneApplicationFrame.Template>
<ControlTemplate>
<layout:TransitioningContentControl Content="{TemplateBinding Content}" Style="{StaticResource TransitioningStyle}">
<layout:TransitioningContentControl.PageTransitionMappings>
<layout:PageTransitionMapping Page="AprilCTP.Views.Favorites.Default" Transition="SwingTransition" />
</layout:TransitioningContentControl.PageTransitionMappings>
</layout:TransitioningContentControl>
</ControlTemplate>
</phoneNavigation:PhoneApplicationFrame.Template>
In this example, the Default.xaml page in the Views/Favorites folder has been mapped to use the SwingTransition. Just like before, all of the transitions used by the TCCC must be in the TCC’s Style definition – the ControlTemplate’s VisualStateManager specifically).
The next last step is to update the way the TCC applies transitions to pages as they are displayed. To do this, we update the TCC’s StartTransition() method as shown below:
private void StartTransition(object oldContent, object newContent)
{
// both presenters must be available, otherwise a transition is useless.
if (CurrentContentPresentationSite != null && PreviousContentPresentationSite != null)
{
PageTransitionMapping transitionMapping = null;
var newPage = newContent as PhoneApplicationPage;
if (newPage != null)
{
string pageType = newPage.GetType().ToString();
transitionMapping = (from m in this.PageTransitionMappings where m.Page == pageType select m).SingleOrDefault();
}
// and start a new transition
if (!IsTransitioning || RestartTransitionOnContentChange)
{
IsTransitioning = true;
if (transitionMapping != null)
{
Transition = transitionMapping.Transition;
}
else
Transition = _standardTransition;
CurrentContentPresentationSite.Content = newContent;
PreviousContentPresentationSite.Content = oldContent;
VisualStateManager.GoToState(this, NormalState, false);
VisualStateManager.GoToState(this, Transition, true);
}
}
}
There are a couple of important points. First, the CurrentContextPresentionSite.Content = and the PreviousContentPresentationState.Content = lines of code have been moved a bit from where they appeared in the original code. Secondly, there is no real error handling for cases where you enter the wrong name for your custom transition inside the App.xaml mapping. This is more “proof of concept” code than production ready code. The TCC has a GetStoryboard method that you can use to make sure the transition is available, it is just a matter of where you want to detect that and then how you want to handle it in case a transition does not exist (fall back to the default transition is probably the easiest).
The last thing we have to do is set the value for _standardTransition. We will set its value in the OnApplyTemplate() method inside the TCC. This method gets called one time when the TCC is first created and the template is applied. We will add the declaration for _standardTransition immediately before the method (stick it where ever you like):
private string _standardTransition;
/// <summary>
/// Builds the visual tree for the TransitioningContentControl control
/// when a new template is applied.
/// </summary>
public override void OnApplyTemplate()
The OnApplyTemplate discovers the value of the TCC Transition property that was set in the Style in the App.xaml file. Setting _standardTransition to this value let’s us use it whenever there is not a custom page transition defined. Update the OnApplyTemplate() method as shown:
^^^^ REST OF METHOD ^^^^
_standardTransition = Transition;
VisualStateManager.GoToState(this, NormalState, false);
}
I have included the source for a working solution here.