Skip to content

Instantly share code, notes, and snippets.

@cucmberium
Created April 9, 2015 11:20
Show Gist options
  • Save cucmberium/3d7aca28753f7f45e172 to your computer and use it in GitHub Desktop.
Save cucmberium/3d7aca28753f7f45e172 to your computer and use it in GitHub Desktop.
Prism.Mvvm.MvvmAppBase for Universal App Platform
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.UI.ApplicationSettings;
using Windows.ApplicationModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.ApplicationModel.Resources;
using Microsoft.Practices.Prism.StoreApps;
using Microsoft.Practices.Prism.Mvvm.Interfaces;
using Windows.Phone.UI.Input;
using Windows.Foundation.Metadata;
namespace Microsoft.Practices.Prism.Mvvm
{
public abstract class MvvmAppBase : Application
{
private bool _isRestoringFromTermination;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
protected MvvmAppBase()
{
this.Suspending += OnSuspending;
}
/// <summary>
/// Gets or sets the session state service.
/// </summary>
/// <value>
/// The session state service.
/// </value>
protected ISessionStateService SessionStateService { get; set; }
/// <summary>
/// Gets or sets the navigation service.
/// </summary>
/// <value>
/// The navigation service.
/// </value>
protected INavigationService NavigationService { get; set; }
/// <summary>
/// Factory for creating the ExtendedSplashScreen instance.
/// </summary>
/// <value>
/// The Func that creates the ExtendedSplashScreen. It requires a SplashScreen parameter,
/// and must return a Page instance.
/// </value>
protected Func<SplashScreen, Page> ExtendedSplashScreenFactory { get; set; }
/// <summary>
/// Gets a value indicating whether the application is suspending.
/// </summary>
/// <value>
/// <c>true</c> if the application is suspending; otherwise, <c>false</c>.
/// </value>
public bool IsSuspending { get; private set; }
/// <summary>
/// Override this method with logic that will be performed after the application is initialized. For example, navigating to the application's home page.
/// </summary>
/// <param name="args">The <see cref="LaunchActivatedEventArgs"/> instance containing the event data.</param>
protected abstract Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args);
/// <summary>
/// Gets the type of the page based on a page token.
/// </summary>
/// <param name="pageToken">The page token.</param>
/// <returns>The type of the page which corresponds to the specified token.</returns>
protected virtual Type GetPageType(string pageToken)
{
var assemblyQualifiedAppType = this.GetType().GetTypeInfo().AssemblyQualifiedName;
var pageNameWithParameter = assemblyQualifiedAppType.Replace(this.GetType().FullName, this.GetType().Namespace + ".Views.{0}Page");
var viewFullName = string.Format(CultureInfo.InvariantCulture, pageNameWithParameter, pageToken);
var viewType = Type.GetType(viewFullName);
if (viewType == null)
{
var resourceLoader = ResourceLoader.GetForCurrentView(PrismConstants.StoreAppsInfrastructureResourceMapId);
throw new ArgumentException(
string.Format(CultureInfo.InvariantCulture, resourceLoader.GetString("DefaultPageTypeLookupErrorMessage"), pageToken, this.GetType().Namespace + ".Views"),
"pageToken");
}
return viewType;
}
/// <summary>
/// Used for setting up the list of known types for the SessionStateService, using the RegisterKnownType method.
/// </summary>
protected virtual void OnRegisterKnownTypesForSerialization() { }
/// <summary>
/// Override this method with the initialization logic of your application. Here you can initialize services, repositories, and so on.
/// </summary>
/// <param name="args">The <see cref="IActivatedEventArgs"/> instance containing the event data.</param>
protected virtual Task OnInitializeAsync(IActivatedEventArgs args)
{
return Task.FromResult<object>(null);
}
/// <summary>
/// Resolves the specified type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A concrete instance of the specified type.</returns>
protected virtual object Resolve(Type type)
{
return Activator.CreateInstance(type);
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used when the application is launched to open a specific file, to display
/// search results, and so forth.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
var rootFrame = await InitializeFrameAsync(args);
// If the app is launched via the app's primary tile, the args.TileId property
// will have the same value as the AppUserModelId, which is set in the Package.appxmanifest.
// See http://go.microsoft.com/fwlink/?LinkID=288842
string tileId = AppManifestHelper.GetApplicationId();
if (rootFrame != null && (!_isRestoringFromTermination || (args != null && args.TileId != tileId)))
{
await OnLaunchApplicationAsync(args);
}
// Ensure the current window is active
Window.Current.Activate();
}
/// <summary>
/// Initializes the Frame and its content.
/// </summary>
/// <param name="args">The <see cref="IActivatedEventArgs"/> instance containing the event data.</param>
/// <returns>A task of a Frame that holds the app content.</returns>
protected async Task<Frame> InitializeFrameAsync(IActivatedEventArgs args)
{
var rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
if (ExtendedSplashScreenFactory != null)
{
Page extendedSplashScreen = this.ExtendedSplashScreenFactory.Invoke(args.SplashScreen);
rootFrame.Content = extendedSplashScreen;
}
var frameFacade = new FrameFacadeAdapter(rootFrame);
//Initialize MvvmAppBase common services
SessionStateService = new SessionStateService();
//Configure VisualStateAwarePage with the ability to get the session state for its frame
VisualStateAwarePage.GetSessionStateForFrame =
frame => SessionStateService.GetSessionStateForFrame(frameFacade);
//Associate the frame with a key
SessionStateService.RegisterFrame(frameFacade, "AppFrame");
NavigationService = CreateNavigationService(frameFacade, SessionStateService);
if (ApiInformation.IsTypePresent("Windows.UI.ApplicationSettings.SettingsPane"))
SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;
if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
HardwareButtons.BackPressed += OnHardwareButtonsBackPressed;
// Set a factory for the ViewModelLocator to use the default resolution mechanism to construct view models
ViewModelLocationProvider.SetDefaultViewModelFactory(Resolve);
OnRegisterKnownTypesForSerialization();
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
await SessionStateService.RestoreSessionStateAsync();
}
await OnInitializeAsync(args);
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore the saved session state and navigate to the last page visited
try
{
SessionStateService.RestoreFrameState();
NavigationService.RestoreSavedNavigation();
_isRestoringFromTermination = true;
}
catch (SessionStateServiceException)
{
// Something went wrong restoring state.
// Assume there is no state and continue
}
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
return rootFrame;
}
/// <summary>
/// Creates the navigation service.
/// </summary>
/// <param name="rootFrame">The root frame.</param>
/// <param name="sessionStateService">The session state service.</param>
/// <returns>The initialized navigation service.</returns>
private INavigationService CreateNavigationService(IFrameFacade rootFrame, ISessionStateService sessionStateService)
{
var navigationService = new FrameNavigationService(rootFrame, GetPageType, sessionStateService);
return navigationService;
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
IsSuspending = true;
try
{
var deferral = e.SuspendingOperation.GetDeferral();
//Bootstrap inform navigation service that app is suspending.
NavigationService.Suspending();
// Save application state
await SessionStateService.SaveAsync();
deferral.Complete();
}
finally
{
IsSuspending = false;
}
}
/// <summary>
/// Gets the Settings charm action items.
/// </summary>
/// <returns>The list of Setting charm action items that will populate the Settings pane.</returns>
protected virtual IList<SettingsCommand> GetSettingsCommands()
{
return new List<SettingsCommand>();
}
protected virtual void OnHardwareButtonsBackPressed(object sender, BackPressedEventArgs e)
{
if (NavigationService.CanGoBack())
{
NavigationService.GoBack();
e.Handled = true;
}
else this.Exit();
}
/// <summary>
/// Called when the Settings charm is invoked, this handler populates the Settings charm with the charm items returned by the GetSettingsCommands function.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="SettingsPaneCommandsRequestedEventArgs"/> instance containing the event data.</param>
private void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
if (args == null || args.Request == null || args.Request.ApplicationCommands == null)
{
return;
}
var applicationCommands = args.Request.ApplicationCommands;
var settingsCommands = GetSettingsCommands();
foreach (var settingsCommand in settingsCommands)
{
applicationCommands.Add(settingsCommand);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment