Saturday, August 31, 2013

Humorous Speech

Last week I participated in a humorous speech contest at Toastmasters. I didn’t win, I was second of three.

I can be funny as part of a normal speech, I can get one or two laugh lines I to a 5 to 7 minute speech. Since the purpose of the speech is to be funny, I kinda freak out.

In a humorous speech the audience is expecting me to be funny, so I can’t use the element of surprise. In a normal speech, a failed joke doesn’t necessarily sink the speech.

In a humorous speech the audience is expecting higher joke density. My usual Toastmaster speech has two laugh lines and perhaps an unintentional joke hidden within. So I need to triple my joke count without them sounding forced.

There is a big difference between the fellow who is funny and the comedian; any time the civilian is funny it is a bonus, any time the pro fails to be funny it is a failure.

Wednesday, July 31, 2013

Take Improv after you move

At the beginning of June I moved from Spokane to Bellevue to work at Microsoft. I signed up for improv class with Unexpected Productions even before I left Spokane. This was a brilliant move! The quarter ended last night, which makes me sad. I have already signed up for the 200 level class that starts in September.

Since then I have gone to the Matador (a Mexican themed bar in downtown Redmond) after a couple of my classes, to a couple of shows with some classmates, found a Toastmasters club (again with a couple of classmates who already belong).

Pre-improv Jack would still be hanging out alone in his apartment two months out after moving to a new city. My previous improv experience has given me some better social skills than I had before; improv class creates openness in the students.

If I ever move again I will look for improv classes in my new community. I will start at the beginning (even if I become a player at UP) and move up with my class. My objective isn’t necessarily to become a great improviser, but to have the opportunity to play and become more skilled at dealing with people (as opposed to technology).

I know that both readers of this blog are probably saying “enough of this improv stuff already!” This stuff has worked for me and I am excited about the results. I don’t know that pre-improv would have gotten this job. It has given me the courage to get up in front of people in non-improv situations; I have spoken at a half dozen code camps and I am working the Toastmasters program.

Even if I’m a really bad improviser, it’s worth it.

Wednesday, June 26, 2013

Back at Microsoft

I took another contract job at Microsoft; back for the first time in almost 13 years. I started at the beginning of June. I’m excited to work on cutting edge technology with smart people (try to be the dumbest person in the room if you can).

What am I working on? I can’t say.

Thursday, May 09, 2013

NPR Teenage Diaries Revisited on Tourette’s

On NPR’s All Things Considered, they did a story on Josh Cutler and his experience with Tourette’s syndrome. It got me to think about, my own experience,so I wrote this letter to Josh through NPR’s comment page.

Josh Cutler,

I don’t know what you will say about having Tourette’s at 50, however I can tell you about my experience at 49.

In my generation, we weren’t all that aware of Tourette’s, I was just a troubled kid in Special Education who wasn’t supposed to go to college (but I did graduate from Central Washington University in 5 years). I wasn’t diagnosed until after I turned 40.

Now I am a computer programmer. I’ve worked for many small companies and one really large one. I think I do solitary work because I don’t trust my behavior. I admire you for having the guts to teach; I’m sad that it didn’t go well. I wish the world would be more supportive of people like us. I relate to children, I’m scared of adult’s reaction to me.

I totally relate with your jujitsu class; over the last few years I’ve been taking this Improv class over and over again; I believe that keeps me sane. I walk over a mile to work everyday day. The motion of the scene work and walking all over town helps me keep my ticks in check. I think the Improv has been good to me because it allows me to play with behavior and just be childlike among other grown-ups.

Most of my ticks are in my face shoulder, leg neck and elsewhere in my body. At times the energy behind the twitch can become overwhelming; sometimes I will shake all over for an hour at night. I’ve twitched to the point of pain. I don’t cuss, I have trouble saying the F-word in the locker room where I’m supposed to have a foul mouth. I do have a problem with “angry” outbursts.

I too had my bad Tourette’s event with long term consequences. My incident happened at Microsoft in 2000. I had been “normal” for over a year and then I burst. So, based in a moderate episode I am banned from ever working there again, and as far as I can tell, it is still in force. [NOTE: it isn't still in force, see my next post]

The curse of Tourette’s is that it leads to bazaar behavior. When I’ve behaved badly it is scary because it is different, not because it is necessarily dangerous.

Thank you, Josh, for sharing your life with us. It means a lot to me. You’ve given me the opportunity to put things into words.

Best of luck

Jack Stephens

Spokane

I think there is a point where it is good to put it out there.

Sunday, April 14, 2013

Compare two DataSets for testing

There is a client that has several statements that are rendered as Crystal Reports; we bind the Crystal Reposts to ADO.NET DataSets. The DataSets are loaded from stored procedures in the usual way. Right now we are printing several of these statements and some poor clerk has to compare those values with an earlier correct one.

My idea is to store the DataSets of known good statements and then I can automatically compare them with a new DataSet loaded from the stored procedure. So, over the weekend I wrote these classes to do the comparisons:

The Code

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace CompareDS
{
    /// <summary>
    /// Compare the contents of DataSets or DataTables 
    /// </summary>
    public class CompareDataSet
    {
        /// <summary>
        /// Compare the content of two DataSets
        /// </summary>
        /// <param name="fromDS">The DataSet considered to be correct</param>
        /// <param name="toDS">The DataSet to be tested</param>
        /// <returns>A list of Inconsistencies</returns>
        public static List<CompareDifference> DoCompareDataSet(
            DataSet fromDS, DataSet toDS)
        {
            var rVal = new List<CompareDifference>();

            // Make sure that the table count match
            if (fromDS.Tables.Count != toDS.Tables.Count)
            {
                rVal.Add(new CompareDifference
            {
                Message = string.Format("Non maching # of tables: {0} != {1}", 
                    fromDS.Tables.Count, toDS.Tables.Count)
                });
            }
            // Process the smaller # of tables
            int minColCount = Math.Min(fromDS.Tables.Count, toDS.Tables.Count);
            for (int i = 0; i < minColCount; ++i)
            {
                DataTable fromTable = fromDS.Tables[i];
                DataTable toTable = toDS.Tables[i];
                string tableName = fromTable.TableName;
                rVal.AddRange(DoCompareTable(fromTable, toTable, tableName, i));
            }
            return rVal;
        }
        /// <summary>
        /// Compare the content of two DataTables
        /// </summary>
        /// <param name="fromTable">The DataTable considered to be correct</param>
        /// <param name="toTable">The DataTable to be tested</param>
        /// <param name="tableName">The Name of the table to be compared</param>
        /// <param name="tableNumber">The zero based table number</param>
        /// <returns>A list of Inconsistencies</returns>
        public static List<CompareDifference> DoCompareTable(DataTable fromTable, 
            DataTable toTable, string tableName = "Table", int tableNumber = 0)
        {
            var rVal = new List<CompareDifference>();
            // Number of Rows should match
            if (fromTable.Rows.Count != toTable.Rows.Count)
            {
                rVal.Add(new CompareDifference
                {
                    TableName = tableName,
                    TableNumber = tableNumber,
                    Message = string.Format("Non maching # of rows: {0} != {1}", 
                        fromTable.Rows.Count, toTable.Rows.Count)
                });
            }
            // Create new CompareDataTable for this table
            var compTables = new CompareDataTable     (fromTable, toTable, 
                tableName, tableNumber);
            int minColCount = Math.Min(fromTable.Rows.Count, toTable.Rows.Count);
            for (int i = 0; i < minColCount; ++i)
            {
                rVal.AddRange(compTables.CompareRow(
                    fromTable.Rows[i], toTable.Rows[i], i));
            }
            return rVal;
        }
    }
    /// <summary>
    /// Compares a DateTable row by row.
    /// I use a seperate non-static class so I don't have to re-aquire
    /// the table's Columns (Overkill, I know)
    /// </summary>
    public class CompareDataTable
    {
        private DataTable _fromTable;
        private DataTable _toTable;
        private DataColumnCollection _fromColumns;
        private DataColumnCollection _toColumns;
        private string _tableName;
        public int _tableNumber;

        /// <summary>
        /// Constructor: I use this class to avoid re-aquiring Columns
        /// for each row.
        /// </summary>
        /// <param name="fromTable">The DataTable considered to be correct</param>
        /// <param name="toTable">The DataTable to be tested</param>
        /// <param name="tableName">The Name of the table to be compared</param>
        /// <param name="tableNumber">The zero based table number</param>
        public CompareDataTable(DataTable fromTable, DataTable toTable, 
            string tableName, int tableNumber)
        {
             _fromTable = fromTable;
             _toTable = toTable;
             _tableName = tableName;
             _tableNumber = tableNumber;

             // Remember the Table Columns
             _fromColumns = _fromTable.Columns;
             _toColumns = _toTable.Columns;
        }
        /// <summary>
        /// Compare the content of two DataRows
        /// </summary>
        /// <param name="fromRow">The DataRow considered to be correct</param>
        /// <param name="toRow">The DataRow  to be tested</param>
        /// <param name="rowNumber">The zero based number of the row</param>
        /// <returns>A list of Inconsistencies</returns>
        public List<CompareDifference> CompareRow(DataRow fromRow, 
        DataRow toRow, int rowNumber)
        {
            var rVal = new List<CompareDifference>();
            int minColCount = Math.Min(fromRow.ItemArray.Count(), 
            toRow.ItemArray.Count());

            for (int i = 0; i < minColCount; ++i)
            {
                object fromCell = fromRow.ItemArray[i];
                object toCell = toRow.ItemArray[i];
                string fromColName = _fromColumns[i].ColumnName;
                string toColName = _toColumns[i].ColumnName;
                // Column names must match
                if (fromColName != toColName)
                {
                    rVal.Add(new CompareDifference
                    {
                        TableName = _tableName,
                        TableNumber = _tableNumber,
                        RowNumber = rowNumber,
                        ColumnName = fromColName,
                        ColumnNumber = i,
                        Message = string.Format(
                            "Non matching column names \"{0}\" != \"{1}\"", 
                            fromColName, toColName)
                        });
                }
                // Type must match
                if (fromCell.GetType() != toCell.GetType())
                {
                    rVal.Add(new CompareDifference
                    {
                        TableName = _tableName,
                        TableNumber = _tableNumber,
                        RowNumber = rowNumber,
                        ColumnName = fromColName,
                        ColumnNumber = i,
                        ExpectedValue = fromCell.ToString(),
                        ActualValue = toCell.ToString(),
                        Message = string.Format(
                            "No matching types \"{0}\" != \"{1}\"", 
                            fromCell.GetType(), toCell.GetType())
                    });
                }
                // And values (string compare for simplicity)
                else if (fromCell.ToString() != toCell.ToString())
                {
                    rVal.Add(new CompareDifference
                    {
                        TableName = _tableName,
                        TableNumber = _tableNumber,
                        RowNumber = rowNumber,
                        ColumnName = fromColName,
                        ColumnNumber = i,
                        ExpectedValue = fromCell.ToString(),
                        ActualValue = toCell.ToString(),
                        Message = string.Format(
                            "No matching values \"{0}\" != \"{1}\"", 
                            fromCell, toCell)
                    });
                }
            }
            return rVal;
        }
    }
    /// <summary>
    /// Simple class to store error messages
    /// </summary>
    public class CompareDifference
    {
        /// <summary>
        /// The Name of the Table 
        /// where the inconsistancy exists
        /// </summary>
        public int TableNumber { get; set; }
        /// <summary>
        /// The zero based number of the Table 
        /// where the inconsistancy exists
        /// </summary>
        public string TableName { get; set; }
        /// <summary>
        /// The zero based number of the column
        /// where the inconsistancy exists
        /// </summary>
        public int? ColumnNumber { get; set; }
        /// <summary>
        /// The name of the column
        /// where the inconsistancy exists
        /// </summary>
        public string ColumnName { get; set; }
        /// <summary>
        /// The number of the row 
        /// where the inconsistancy exists
        /// </summary>
        public int? RowNumber { get; set; }
        /// <summary>
        /// The expected value
        /// </summary>
        public string ExpectedValue { get; set; }
        /// <summary>
        ///  The actual value
        /// </summary>
        public string ActualValue { get; set; }
        /// <summary>
        /// An error message
        /// </summary>
        public string Message { get; set; }
    }
}

Sunday, March 10, 2013

Displaying Status with Live Tiles

Brain Dead Simple Windows RT App Part 4

In Windows Phone, Microsoft introduced the idea of Tiles that could provide the use with updates. Your tile is important because it is the one thing that is always there whispering to the user “run me” day and night. There are four types of updates, Local, Scheduled, Periodic and Push. Because this is a basic level intro article, I’m going to ignore Scheduled, Periodic and Push and work on Local (in the wild, you will probably need to use one of the other three).

Windows 8 offers a total of 46 tile templates that are enumerated in TileTemplateType. To update a tile you:

  1. Get the Template with TileUpdateManager.GetTemplateContent
  2. Create a notification or a new TileNotification object with a reference to the template you retrieved on Step 1 and set any ExpirationTime
  3. Set notification text on the Template XML you retrieved on Step 1
  4. Update Live Tile Create a TileUpdater and call its Update with a the TileNotification created in Step 1

Back to the App

I’m lazy, so I don’t even want to open my app to know how excited I am. I can use the apps tile to remind me. Now I only need to open the app to use the more advanced features like changing my excitement level.

NOTE: In this app, the settings roam but the Live Tile does not. Since this is a really simple demo, I’m OK with that, I would never ship an app like this.

public static void SetLiveTile(string title, string body, int? seconds = null)
{
    // Get tile template.
    var tileTemplate = TileTemplateType.TileSquareBlock;
    XmlDocument tileXml = TileUpdateManager.GetTemplateContent(tileTemplate);

    // Create notification.
    var notification = new TileNotification(tileXml);
    if (seconds.HasValue)
    {
        notification.ExpirationTime = DateTime.Now + 
        TimeSpan.FromSeconds(seconds.Value);
    }

    // Set notification text.
    XmlNodeList nodes =    tileXml.GetElementsByTagName("text");
    nodes[0].InnerText = title;
    nodes[1].InnerText = body;

    // Update Live Tile.
    var upd = TileUpdateManager.CreateTileUpdaterForApplication();
    upd.Update(notification);
}

And I add the following line to the end of saveSettings()

SetLiveTile(string.Format("{0}!", _exlamationPointCount), HelloMessage, 3600);

Complete Code


using System;
using System.ComponentModel;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace HelloWindows
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private const string BASE_MESSAGE = "Hello Windows";

        public MainPage()
        {
            this.InitializeComponent();

            // Load Settings here:
            loadSettings();
            HelloMessage = setMessge(_exlamationPointCount);
            this.DataContext = this;
        }


        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new  PropertyChangedEventArgs(propertyName));
            }
        }

        public string HelloMessage { get; set; }


        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  
        /// The Parameter property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private int _exlamationPointCount = 0;

        private string setMessge(int exlamationPointCount)
        {
            if (exlamationPointCount > 0)
            {
                return _baseMessage + new string('!', exlamationPointCount);
            }
            else
            {
                return _baseMessage;
            }
        }

        private void addPoint_Click(object  sender, RoutedEventArgs e)
        {
            HelloMessage = setMessge(++_exlamationPointCount);
            RaisePropertyChanged("HelloMessage");
            RaisePropertyChanged("IsRemovePossible");
            // This is overkill
            saveSettings();
        }

        private void removePoint_Click(object sender, RoutedEventArgs e)
        {
            if (_exlamationPointCount >= 1)
            {
                HelloMessage = setMessge(--_exlamationPointCount);
                RaisePropertyChanged("HelloMessage");
                RaisePropertyChanged("IsRemovePossible");
                // This is overkill
                saveSettings();
            }
        }

        // Make it possible to disable Remove Point button when there
        // is nothing left to remove
        public bool IsRemovePossible
        {
            get { return _exlamationPointCount > 0; }
        }
        // I replace most refrence to BASE_MESSAGE to _baseMessage
        private string _baseMessage = BASE_MESSAGE;

        // Ensure that RoamingSettings has been loaded
        private static ApplicationDataContainer _roamingSettings;
        public static ApplicationDataContainer RoamingSettings
        {
            get
            {
              if (_roamingSettings == null)
              {
                  // If I don't want roaming, use 
                  // ApplicationData.Current.LocalSettings;
                  _roamingSettings = ApplicationData.Current.RoamingSettings;
              }
              return _roamingSettings;
            }
        }

        // I know that saving every time the value is changed,
        // in real life I'd save the data in App.OnSuspending()
        private void saveSettings()
        {
            // I combine both values into a ApplicationDataCompositeValue
            // and save them both to "HighPriority"
            var composite = new ApplicationDataCompositeValue();
            composite["baseMessage"] = _baseMessage;
            composite["exlamationPointCount"] = _exlamationPointCount;
            RoamingSettings.Values["HighPriority"] = composite;

           SetLiveTile(string.Format("{0}!" , _exlamationPointCount),
           HelloMessage, 3600);
        }
        // To be called from the constructor
        private void loadSettings()
        {
            // I get "HighPriority" cast it to ApplicationDataCompositeValue
            // and extract the values.
            var composite = (ApplicationDataCompositeValue)
            RoamingSettings.Values["HighPriority"];
            if (composite != null) // the first time it will be null
            {
                _baseMessage = (string)composite["baseMessage"];
                _exlamationPointCount = (int)composite["exlamationPointCount"];
          }
      }


      public static void SetLiveTile(string     title, string body, int? seconds = null)
      {
          // Get tile template.
          var tileTemplate = TileTemplateType.TileSquareBlock;
          XmlDocument tileXml = TileUpdateManager.GetTemplateContent(tileTemplate);

          // Create notification.
          var notification = new TileNotification(tileXml);
          if (seconds.HasValue)
          {
              notification.ExpirationTime = DateTime.Now +
              TimeSpan.FromSeconds(seconds.Value);
          }

          // Set notification text.
          XmlNodeList nodes = tileXml.GetElementsByTagName("text");
          nodes[0].InnerText = title;
          nodes[1].InnerText = body;

          // Update Live Tile.
          var upd = TileUpdateManager.CreateTileUpdaterForApplication();
          upd.Update(notification);
      }
    }
}

My Brain Dead Simple Windows RT App: The Series

Thursday, March 07, 2013

Roaming data with ApplicationData

Brain Dead Simple Windows RT App Part 3

In Window 8, you should be able to move between your devices and your apps should follow you. In the Microsoft documentation, there is a lot of talk about some office worker who likes to start some task on her office computer (possibly when her boss’s back is turned) and finish them on the bus with her tablet. The feature that they are pushing with these examples is Roaming.

So by the time that Emily (we can call her that) turns off her computer at work, the app needs to save some state data to the cloud, when she opens the same app on her tablet, it goes out and gets the that data from the cloud and uses it to remember where she left off.

All the stuff you need to do this is in Windows.Storage.ApplicationData. You have a choice of where you want to save it (Roaming or Local) and how (ApplicationDataContainer or StorageFolder).

Roaming data is first stored locally and then pushed to Microsoft servers on the cloud; there is a limit to how much data can be roamed, you can use RoamingStorageQuota to find out how much (note that if you exceed the quota, it will just fail without any errors at all).

Local stores the data locally so no roaming occurs but you have more space to work with and can be used for things that aren’t appropriate to roam.

ApplicationDataContainer (used for RoamingSettings & LocalSettings) contains a property called Values which is a dictionary that contains the settings. Each value in the dictionary is handled separately, so one value may be roamed before the other. You can use ApplicationDataCompositeValue to stick values together and they will be treated as a single unit. Oh, yea, there is a special value in the dictionary called “HighPriority” that will be roamed before everything else.

StorageFolder (used for RoamingFolder, LocalFolder & TemporaryFolder) gives you a handle to a folder in the file system that you can use to read and write files. Files in RoamingFolder will be synced with the magic Microsoft server (if the total size doesn’t exceed RoamingStorageQuota. Files in LocalFolder are not synced but will stay around for a while; the files in TemporaryFolder don’t.

Back to the App

When I run my Hello app, I can press the Exclamation Point Button 42 times but when I close it down and open it up again, if forgets. So, when I open the app again, there are NO exclamation points and that dampens my enthusiasm; I want to keep my excitement so the exclamation points need to stay. We can solve this problem with Roaming!

 

// I replace most refrence to BASE_MESSAGE to _baseMessage
private string _baseMessage = BASE_MESSAGE;

// Ensure that RoamingSettings has been loaded
private static ApplicationDataContainer _roamingSettings;
public static ApplicationDataContainer RoamingSettings
{
    get
    {
        if (_roamingSettings == null)
        {
            //If I don't want roaming, use ApplicationData.Current.LocalSettings;
            _roamingSettings = ApplicationData.Current.RoamingSettings;
        }
        return _roamingSettings;
    }
}

// I know that saving every time the value is changed,
// in real life I'd save the data in App.OnSuspending()
private void saveSettings()
{
    // I combine both values into a ApplicationDataCompositeValue
    // and save them both to "HighPriority"
    var composite = new ApplicationDataCompositeValue();
    composite["baseMessage"] = _baseMessage;
    composite["exlamationPointCount"] = _exlamationPointCount;
    RoamingSettings.Values["HighPriority"] = composite;
}
// To be called from the constructor
private void loadSettings()
{
    // I get "HighPriority" cast it to ApplicationDataCompositeValue
    // and extract the values.
    var composite = (ApplicationDataCompositeValue)
    RoamingSettings.Values["HighPriority"];
    if (composite != null) // the first time it will be null
    {
        _baseMessage = (string)composite["baseMessage"];
        _exlamationPointCount = (int)composite["exlamationPointCount"];
    }
}

And I change the constructor to look like:

public MainPage()
{
    this.InitializeComponent();

    // Load Settings here:
    loadSettings();
    HelloMessage = setMessge(_exlamationPointCount);
    this.DataContext = this;
}

And the setMessage() to the field instead of the constant:

private string setMessge(int exlamationPointCount)
{
    if (exlamationPointCount > 0)
    {
        return _baseMessage + new string('!', exlamationPointCount);
    }
    else
    {
        return _baseMessage;
    }
}

Since I haven’t changed the markup, I won’t repost that part (see my previous post), but I will repost the code behind (MainPage.xaml.cs):

using System.ComponentModel;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace HelloWindows
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private const string BASE_MESSAGE = "Hello Windows";

        public MainPage()
        {
            this.InitializeComponent();

            // Load Settings here:
            loadSettings();
            HelloMessage = setMessge(_exlamationPointCount);
            this.DataContext = this;
        }


        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new  PropertyChangedEventArgs(propertyName));
            }
        }

        public string HelloMessage { get; set; }


        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  
        /// The Parameter property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private int _exlamationPointCount = 0;

        private string setMessge(int  exlamationPointCount)
        {
            if (exlamationPointCount > 0)
            {
                return _baseMessage + new string('!', exlamationPointCount);
            }
            else
            {
                return _baseMessage;
            }
        }

        private void addPoint_Click(object      sender, RoutedEventArgs e)
        {
            HelloMessage = setMessge(++_exlamationPointCount);
            RaisePropertyChanged("HelloMessage");
            RaisePropertyChanged("IsRemovePossible");
            // This is overkill
            saveSettings();
        }

        private void removePoint_Click(object sender, RoutedEventArgs e)
        {
            if (_exlamationPointCount >= 1)
            {
                HelloMessage = setMessge(--_exlamationPointCount);
                RaisePropertyChanged("HelloMessage");
                RaisePropertyChanged("IsRemovePossible");
                // This is overkill
                saveSettings();
            }
        }

        // Make it possible to disable Remove Point button when there
        // is nothing left to remove
        public bool IsRemovePossible
        {
            get { return _exlamationPointCount > 0; }
        }
        // I replace most refrence to BASE_MESSAGE to _baseMessage
        private string _baseMessage = BASE_MESSAGE;

        // Ensure that RoamingSettings has been loaded
        private static ApplicationDataContainer _roamingSettings;
        public static ApplicationDataContainer RoamingSettings
        {
            get
            {
                if (_roamingSettings == null)
                {
                    // If I don't want roaming, use 
                    // ApplicationData.Current.LocalSettings;
                    _roamingSettings = ApplicationData.Current.RoamingSettings;
                }
                return _roamingSettings;
            }
        }

        // I know that saving every time the value is changed,
        // in real life I'd save the data in App.OnSuspending()
        private void saveSettings()
        {
            // I combine both values into a ApplicationDataCompositeValue
            // and save them both to "HighPriority"
            var composite = new  ApplicationDataCompositeValue();
            composite["baseMessage"] = _baseMessage;
            composite["exlamationPointCount"] = _exlamationPointCount;
            RoamingSettings.Values["HighPriority"] = composite;
        }
        // To be called from the constructor
        private void loadSettings()
        {
            // I get "HighPriority" cast it to ApplicationDataCompositeValue
            // and extract the values.
            var composite = (ApplicationDataCompositeValue)
            RoamingSettings.Values["HighPriority"];
            if (composite != null           ) // the first time it will be null
            {
                _baseMessage = (string)composite["baseMessage"];
                _exlamationPointCount = (int)composite["exlamationPointCount"];
            }
        }
    }
}

My Brain Dead Simple Windows RT App: The Series