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; /// /// 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(). /// protected MvvmAppBase() { this.Suspending += OnSuspending; } /// /// Gets or sets the session state service. /// /// /// The session state service. /// protected ISessionStateService SessionStateService { get; set; } /// /// Gets or sets the navigation service. /// /// /// The navigation service. /// protected INavigationService NavigationService { get; set; } /// /// Factory for creating the ExtendedSplashScreen instance. /// /// /// The Func that creates the ExtendedSplashScreen. It requires a SplashScreen parameter, /// and must return a Page instance. /// protected Func ExtendedSplashScreenFactory { get; set; } /// /// Gets a value indicating whether the application is suspending. /// /// /// true if the application is suspending; otherwise, false. /// public bool IsSuspending { get; private set; } /// /// Override this method with logic that will be performed after the application is initialized. For example, navigating to the application's home page. /// /// The instance containing the event data. protected abstract Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args); /// /// Gets the type of the page based on a page token. /// /// The page token. /// The type of the page which corresponds to the specified token. 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; } /// /// Used for setting up the list of known types for the SessionStateService, using the RegisterKnownType method. /// protected virtual void OnRegisterKnownTypesForSerialization() { } /// /// Override this method with the initialization logic of your application. Here you can initialize services, repositories, and so on. /// /// The instance containing the event data. protected virtual Task OnInitializeAsync(IActivatedEventArgs args) { return Task.FromResult(null); } /// /// Resolves the specified type. /// /// The type. /// A concrete instance of the specified type. protected virtual object Resolve(Type type) { return Activator.CreateInstance(type); } /// /// 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. /// /// Details about the launch request and process. 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(); } /// /// Initializes the Frame and its content. /// /// The instance containing the event data. /// A task of a Frame that holds the app content. protected async Task 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; } /// /// Creates the navigation service. /// /// The root frame. /// The session state service. /// The initialized navigation service. private INavigationService CreateNavigationService(IFrameFacade rootFrame, ISessionStateService sessionStateService) { var navigationService = new FrameNavigationService(rootFrame, GetPageType, sessionStateService); return navigationService; } /// /// 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. /// /// The source of the suspend request. /// Details about the suspend request. 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; } } /// /// Gets the Settings charm action items. /// /// The list of Setting charm action items that will populate the Settings pane. protected virtual IList GetSettingsCommands() { return new List(); } protected virtual void OnHardwareButtonsBackPressed(object sender, BackPressedEventArgs e) { if (NavigationService.CanGoBack()) { NavigationService.GoBack(); e.Handled = true; } else this.Exit(); } /// /// Called when the Settings charm is invoked, this handler populates the Settings charm with the charm items returned by the GetSettingsCommands function. /// /// The sender. /// The instance containing the event data. 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); } } } }