In reading “101 Windows Phone 7 Apps” I discovered that there was a missing reference when following the guide in the book. In all fairness to the authors, the book was published pre-Mango and so it may well have worked on the earlier phone OS. I could have built a 7.0 test project to verify this, but I thought that it was more important that the code example is applicable to the latest developer tools and current Windows Phone 7 edition.

Chapter 1, Tally, is a simple application that increments a number each time that the screen is tapped. The application leverages the Windows Phone 7 isolated storage feature to store and retrieve the last value whenever the user navigates to and from the application.

In the “Updating the Code-Behind” section where the MainPage.xaml.cs file’s source code is modified, there is a using statement pointing to an assembly called WindowsPhoneApp. Well in attempting to implement the author’s code, I could not find the assembly for making the reference nor could I find a previous instruction to create the class during the walk-through. Their use of the assembly and implementation of the class is below.

using System.Windows;
using System.Windows.Navigation;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using WindowsPhoneApp; // For the Setting class

namespace Tally
{
    public partial class MainPage : PhoneApplicationPage
    {
        int count = 0;

        // Remember what the user typed, for future app activations or launches
        Setting<int> savedCount = new Setting<int>("SavedCount",0);
       
        public MainPage()
        {
            InitializeComponent();
        }

        //Handle a tap anywhere on the page (other than the button)
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            this.count++;
            this.CountTextBlock.Text = this.count.ToString("N0");
        }
        // Handle a tap on the button
        private void ResetButtonClick(object sender, RoutedEventArgs e)
        {
            this.count = 0;
            this.CountTextBlock.Text = this.count.ToString("N0");
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            // Persist state when leaving for any reason (Deactivated or Closing)
            this.savedCount.Value = this.count;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
    // Restore persisted state
            this.count = this.savedCount.Value;
            this.CountTextBlock.Text = this.count.ToString("N0");
        }
    }
}

When VisualStudio complained about the Setting class and the using statement and I could not find an assembly to reference I knew that something had changed since publishing. To resolve the issue, I simply created a settings class to manage application persistence using isolated storage settings. By convention, I generally place coding classes in a folder named “Modules” as shown in the image below.

SolutionExplorer

The settings class actually implements the Settings.cs class found on MSDN with added properties to support persisting and retrieving the count. Here is the code for this class.

using System;
using System.IO.IsolatedStorage;

namespace Tally.Modules
{
    public class Settings
    {
        readonly IsolatedStorageSettings _settings;
        const string SavedCountSettingKeyName = "SavedCount";
        const int SavedCountSettingDefault = 0;

        public Settings()
        {
            _settings = IsolatedStorageSettings.ApplicationSettings;
        }

        public T Setting<T>(string key, T defaultValue)
        {
            T value;

            // If the key exists, retrieve the value.
            if (_settings.Contains(key))
            {
                value = (T)_settings[key];
            }
            // Otherwise, use the default value.
            else
            {
                value = defaultValue;
            }
            return value;
        }
        public void Save()
        {
            _settings.Save();
        }
        /// <summary>
        /// Update a setting value for our application. If the setting does not
        /// exist, then add the setting.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool AddOrUpdateValue(string key, Object value)
        {
            bool valueChanged = false;

            // If the key exists
            if (_settings.Contains(key))
            {
                // If the value has changed
                if (_settings[key] != value)
                {
                    // Store the new value
                    _settings[key] = value;
                    valueChanged = true;
                }
            }
            // Otherwise create the key.
            else
            {
                _settings.Add(key, value);
                valueChanged = true;
            }
            return valueChanged;
        }

        /// <summary>
        /// Get the current value of the setting, or if it is not found, set the 
        /// setting to the default setting.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public T GetValueOrDefault<T>(string key, T defaultValue)
        {
            T value;

            // If the key exists, retrieve the value.
            if (_settings.Contains(key))
            {
                value = (T)_settings[key];
            }
            // Otherwise, use the default value.
            else
            {
                value = defaultValue;
            }
            return value;
        }

        /// <summary>
        /// Property to get and set a Password Setting Key.
        /// </summary>
        public int SavedCount
        {
            get
            {
                return GetValueOrDefault(SavedCountSettingKeyName, SavedCountSettingDefault);
            }
            set
            {
                if (AddOrUpdateValue(SavedCountSettingKeyName, value))
                {
                    Save();
                }
            }
        }

    }
}

Now that the class exists, here is an updated implementation of MainPage.xaml.cs.

using System.Windows;
using System.Windows.Navigation;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Tally.Modules;

namespace Tally
{
    public partial class MainPage : PhoneApplicationPage
    {
        private int _count;

        // Remember what the user typed, for future app activations or launches
        private readonly Settings _settings = new Settings();
       

        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        //Handle a tap anywhere on the page (other than the button)
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            _count++;
            CountTextBlock.Text = _count.ToString("N0");
        }
        private void ResetButtonClick(object sender, RoutedEventArgs e)
        {
            _count = 0;
            CountTextBlock.Text = _count.ToString("N0");
        }
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            //Persist state when leaving for any reason (deactivated or closing)
            _settings.SavedCount = _count;
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            _count = _settings.SavedCount;
            CountTextBlock.Text = _count.ToString("N0");
        }
    }
}

Build and run and you will find that persistence is now working.

TallyCapture

While this is a trivial fix for more experienced developers, one that they may not pursue even; for someone who is especially new to development, and may not know where to look to resolve the issue, I hope that this can be of some assistance.

Comments


Comments are closed