Tag Archives: mango

WP7: How to add an EULA page to your application

I’m busy working on a Windows Phone 7 Application and ran into the problem that I want to show the user an End User License Agreement (EULA) or Disclaimer page on start-up.

I want the disclaimer to show up before the MainPage is loaded and when accepted, will redirect the user to the MainPage and makes sure that the user is not able to navigate back to the disclaimer.

Here is the solution I came up with

First our supporting class, the DisclaimerManager.cs Singleton. It uses the IsolatedStorage to check if the user already accepted the disclaimer or not. When the user accepts the disclaimer a file is created in the IsolatedStorage. The IsAccepted boolean lets you know if the user already accepted the disclaimer.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO.IsolatedStorage;
using System.IO;

namespace Classes
{
    public class DisclaimerManager
    {
        #region Fields
        private static readonly DisclaimerManager instance = new DisclaimerManager();
        private const string directory = "disclaimer";
        private const string filename = "shown.txt";
        #endregion

        #region Constructor
        static DisclaimerManager()
        {
        }

        private DisclaimerManager()
        {
            this.Check();
        }
        #endregion

        #region Properties
        public static DisclaimerManager Instance
        {
            get
            {
                return DisclaimerManager.instance;
            }
        }

        public bool IsAccepted { get; private set; }
        #endregion

        #region Private methods
        private void Check()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();

            string path = string.Format(@"{0}\{1}", DisclaimerManager.directory, DisclaimerManager.filename);

            if (storage.FileExists(path))
            {
                this.IsAccepted = true;
            }
        }

        public void Accept()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();

            string path = string.Format(@"{0}\{1}", DisclaimerManager.directory, DisclaimerManager.filename);

            if (!storage.DirectoryExists(DisclaimerManager.directory))
            {
                storage.CreateDirectory(DisclaimerManager.directory);
            }

            if (!storage.FileExists(path))
            {
                string value = "true";

                using (IsolatedStorageFileStream storageFile = storage.CreateFile(path))
                {
                    StreamWriter sw = new StreamWriter(storageFile);
                    sw.Write(value);
                    sw.Close();
                }

                this.IsAccepted = true;
            }
        }
        #endregion
    }
}

Then we need to update App.xaml.cs to make sure the Disclaimer Page is shown before the MainPage is loaded. We do this by attaching an event handler to the Navigating event of the RootFrame.

In App.xaml.cs, in the InitializePhoneApplication() method, after the RootFrame is initialized, add the following:

RootFrame.Navigating += this.RootFrame_Navigating;

Now we implement the event handler. It will check if the Disclaimer is accepted. If not, the DisclaimerPage is loaded. The event handler will detach itself, making sure it will not be called on further navigation in the app.

        private void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            if (!DisclaimerManager.Instance.IsAccepted)
            {
                e.Cancel = true;

                RootFrame.Dispatcher.BeginInvoke(() =>
                    {
                        RootFrame.Navigate(new Uri("/Pages/DisclaimerPage.xaml", UriKind.Relative));
                    }
                );
            }

            RootFrame.Navigating -= this.RootFrame_Navigating;
        }

The DisclaimerPage.xaml



    
    
        
            
            
        

        
        
            
            
        

        
        
    
 
    
        
            
        
    

The Disclaimer.xaml.cs, It will navigate to the MainPage if the user accepts the Disclaimer.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Pages
{
    public partial class DisclaimerPage : PhoneApplicationPage
    {
        public DisclaimerPage()
        {
            InitializeComponent();
        }

        private void ApplicationBarIconButtonClick(object sender, EventArgs e)
        {
            ApplicationBarIconButton button = sender as ApplicationBarIconButton;

            if (button != null)
            {
                if (string.Compare(button.Text, "accept", StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    DisclaimerManager.Instance.Accept();
                    this.NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
                }
            }
        }
    }
}

Now we need to add code in the MainPage.xaml.cs to make sure the user will quit the application when navigating back, instead of getting back to the Disclaimer. Therefore we overwrite the OnNavigated method with the following code:

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            if (this.NavigationService.BackStack.Count() == 1)
            {
                try
                {
                    var a = this.NavigationService.BackStack.ElementAt(0);

                    if (a.Source.ToString().Contains("/Pages/DisclaimerPage.xaml") == true)
                    {
                        this.NavigationService.RemoveBackEntry();
                    }
                }
                catch (Exception ex)
                {
                    ex.PrintDebug();
                }
            }

            base.OnNavigatedTo(e);
        }

The count of the BackStack should be one, we are just arriving from the DisclaimerPage. We will check if the previous page is actual the DisclaimerPage and then remove this page from the stack. Note that in this case our DisclaimerPage.xaml is located in the Pages folder!

That’s all! Hope you like it!

References:
This post, Redirecting an initial navigation, by Peter Torr helped me create this solution.

WP7: PhoneApplicationService.Current.State made easy

UPDATE 7 NOV 2011: Have a look at this post: WP7: Northern Lights WP7 Toolkit v0.0.1 for the latest version of this code example.

I was reading “Programming Windows Phone 7”, a free Microsoft book (as PDF) from Charles Petzold and came across some code on why and how to access the PhoneApplicationService.Current.State (chapter 6, “Page State” paragraph) and thought about writing the following code to improve the usability.
Hope you like it:

    public class StateManager
    {
        private static PhoneApplicationService appService = PhoneApplicationService.Current;

        public static void Set<T>(string name, T value)
        {
            appService.State[name] = value;
        }

        public static T Get<T>(string name)
        {
            T result = default(T);

            if (appService.State.ContainsKey(name))
            {
                result = (T)appService.State[name];
            }

            return result;
        }
    }

It can then be invoked as follows:

Set a value

StateManager.Set<MyObject>("MyApplicationObject", obj);

Get a value

MyObject obj = StateManager.Get<MyObject>("MyApplicationObject");

Hope you like it.