Default page for restoring app state while tombstoning

825 Views Asked by At

I am wondering if there is any way to restore the page state to a standard page in the app after tombstone. For example if the app been tombstoned while the user is on page 2, the restored page always will be the page 1. I have problem on how to restore data from page 2 on my app and I see this method as an alternative to overcome this problem.

public FeedPage()
{
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(FeedPage_Loaded);
    performanceProgressBar.Visibility = System.Windows.Visibility.Collapsed;
    LoadFeed();
}

private void LoadFeed()
{
    FrameworkElement root = Application.Current.RootVisual as FrameworkElement;
    var currentFeed = root.DataContext as FeedViewModel;
    WebClient client = new WebClient();
    performanceProgressBar.IsIndeterminate = true;
    performanceProgressBar.Visibility = System.Windows.Visibility.Visible;
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    client.DownloadStringAsync(new Uri(currentFeed.FeedUrl)); 
    this.DataContext = currentFeed;
    ApplicationBar.IsVisible = false;    
}

...

private void FeedPage_Loaded(object sender, RoutedEventArgs e)
{
    if (!App.ViewModel.IsDataLoaded)
    {
        App.ViewModel.LoadData();
    }
}

My problem is that I don't now how to store currentFeed while tobstone. Every time the app is been activated the currentFeed is null. I have tried many solutions but without result.

public partial class App : Application
{
    private static MainViewModel viewModel = null;

    /// <summary>
    /// A static ViewModel used by the views to bind against.
    /// </summary>
    /// <returns>The MainViewModel object.</returns>
    public static MainViewModel ViewModel
    {
       get
        {
            // Delay creation of the view model until necessary
            if (viewModel == null)
                viewModel = new MainViewModel();

            return viewModel;
        }

    }


    /// <summary>
    /// Provides easy access to the root frame of the Phone Application.
    /// </summary>
    /// <returns>The root frame of the Phone Application.</returns>
    public PhoneApplicationFrame RootFrame { get; private set; }

    /// <summary>
    /// Constructor for the Application object.
    /// </summary>
    public App()
    {
        // Global handler for uncaught exceptions. 
        UnhandledException += Application_UnhandledException;

        // Show graphics profiling information while debugging.
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // Display the current frame rate counters.
            Application.Current.Host.Settings.EnableFrameRateCounter = true;

            // Show the areas of the app that are being redrawn in each frame.
            //Application.Current.Host.Settings.EnableRedrawRegions = true;

            // Enable non-production analysis visualization mode, 
            // which shows areas of a page that are being GPU accelerated with a colored overlay.
            //Application.Current.Host.Settings.EnableCacheVisualization = true;
        }

        // Standard Silverlight initialization
        InitializeComponent();

        // Phone-specific initialization
        InitializePhoneApplication();
    }

    // Code to execute when the application is launching (eg, from Start)
    // This code will not execute when the application is reactivated
    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
    }

    // Code to execute when the application is activated (brought to foreground)
    // This code will not execute when the application is first launched
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
    }

    // Code to execute when the application is deactivated (sent to background)
    // This code will not execute when the application is closing
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
    }

    // Code to execute when the application is closing (eg, user hit Back)
    // This code will not execute when the application is deactivated
    private void Application_Closing(object sender, ClosingEventArgs e)
    {

    }


    // Code to execute if a navigation fails
    private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // A navigation has failed; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

    // Code to execute on Unhandled Exceptions
    private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    {
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // An unhandled exception has occurred; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

    #region Phone application initialization

    // Avoid double-initialization
    private bool phoneApplicationInitialized = false;

    // Do not add any additional code to this method
    private void InitializePhoneApplication()
    {
        if (phoneApplicationInitialized)
            return;

        // Create the frame but don't set it as RootVisual yet; this allows the splash
        // screen to remain active until the application is ready to render.
        RootFrame = new PhoneApplicationFrame();
        RootFrame.Navigated += CompleteInitializePhoneApplication;

        // Handle navigation failures
        RootFrame.NavigationFailed += RootFrame_NavigationFailed;

        // Ensure we don't initialize again
        phoneApplicationInitialized = true;
    }

    // Do not add any additional code to this method
    private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
    {
        // Set the root visual to allow the application to render
        if (RootVisual != RootFrame)
            RootVisual = RootFrame;

        // Remove this handler since it is no longer needed
        RootFrame.Navigated -= CompleteInitializePhoneApplication;
    }

    #endregion
}

}

This is my app.xaml.cs as is right now without any changes. With this code, tombstone works fine in mainpage and detailspage but not (of course) in the feedpage.

2

There are 2 best solutions below

2
On

I have problem on how to restore data from page 2 on my app and I see this method as an alternative to overcome this problem.

Why not solve this, your real problem? What you're asking for is unlikely to pass marketplace certification, and would generally be considered a poor user experience.

Restoring data is super easy. So there's no excuse for not doing it.

Update

Well, this looks rather suspecious

FrameworkElement root = Application.Current.RootVisual as FrameworkElement;
currentFeed = root.DataContext as FeedViewModel;

Surely the RootVisual would be the page itself that you're attempting to display? Otherwise, it's another page, that's not being loaded at all.

The solution would be to AVOID using the DataContext from Application.Current.RootVisual. It's generally poor practice, if you ask me.

So either you need to persist your ViewModel manually in the State property, or you need to resolve it in a alternative way (I'll recommend the latter).

But basically you need to read more about how to develop for the platform. Take a look at some examples/tutorials that are known to work.

1
On

Have a look at the following methods in your App.xaml.cs:

private void Application_Deactivated(object sender, DeactivatedEventArgs e)

private void Application_Activated(object sender, ActivatedEventArgs e)

Here is the place you should save and load state data from and to Isolated Storage.

This would also be the place you could force the app to navigate to another page but I would strongly advise against that. The user does not expect this behavior, maybe you will not even be published at the marketplace. And it is not hard to do at all, all you have to do is load and save your state in these methods.

What did you try to do so far? Where exactly lies the problem?