PunchClock: Source Code
May 19, 2012Here is the source code for my first Windows Phone application. It has a few thing I would do differently now but I can admit this baby is a bit ugly. 🙂
Download PunchClock.WP7 Solution
This solution requires Telerik RadControls for Windows Phone. You can download a trial here.
First page is MainPage.xaml:
 <phone:PhoneApplicationPage    x:Class="PunchClock.WP7.MainPage"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:my="clr-namespace:Microsoft.Advertising.Mobile.UI;assembly=Microsoft.Advertising.Mobile.UI" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"    FontFamily="{StaticResource PhoneFontFamilyNormal}"    FontSize="{StaticResource PhoneFontSizeNormal}"    Foreground="{StaticResource PhoneForegroundBrush}"    SupportedOrientations="Portrait" Orientation="Portrait"    shell:SystemTray.IsVisible="True">    <!--LayoutRoot is the root grid where all page content is placed-->    <Grid x:Name="LayoutRoot">        <Grid.Background>            <ImageBrush ImageSource="/Images/background.png">              <ImageBrush.Stretch>Fill</ImageBrush.Stretch>                <ImageBrush.Opacity>0.3</ImageBrush.Opacity>            </ImageBrush>        </Grid.Background>  <Grid.RowDefinitions>            <RowDefinition Height="Auto"/>            <RowDefinition Height="*"/>        </Grid.RowDefinitions>        <!--TitlePanel contains the name of the application and page title-->        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">            <TextBlock x:Name="ApplicationTitle" Text="PUNCHCLOCK" Style="{StaticResource PhoneTextNormalStyle}"/>            <TextBlock x:Name="PageTitle" Text="send email" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>        </StackPanel>        <!--ContentPanel - place additional content here-->        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">            <StackPanel VerticalAlignment="Top" Name="ButtonsStackPanel" Width="420" Height="391" Margin="18,0">                <Button Content="Start Day" Height="93" Name="DayStartButton" Width="374" Click="DayStartButton_Click" />                <Button Content="Start Lunch" Height="93" Name="LunchStartButton" Width="374" Click="LunchStartButton_Click" />                <Button Content="End Lunch" Height="93" Name="LunchEndButton" Width="374" Click="LunchEndButton_Click" />                <Button Content="End Day" Height="93" Name="DayEndButton" Width="374" Click="DayEndButton_Click" />            </StackPanel>        </Grid>        <my:AdControl Height="86" HorizontalAlignment="Left" Margin="0,444,0,0" VerticalAlignment="Top" Width="480" Grid.Row="1">            <my:AdControl.Name>mainPageAdControl</my:AdControl.Name>            <my:AdControl.ApplicationId>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</my:AdControl.ApplicationId>            <my:AdControl.AdUnitId>XXXXXXXX</my:AdControl.AdUnitId>            <my:AdControl.IsAutoRefreshEnabled>true</my:AdControl.IsAutoRefreshEnabled>        </my:AdControl>    </Grid> </phone:PhoneApplicationPage>
The code behind file (MainPage.xaml.cs) contains most of the business logic for the application.
using System; using System.Windows; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; using PunchClock.WP7.Business; using Telerik.Windows.Controls; namespace PunchClock.WP7 { public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); RadDiagnostics radDiagnostics = new RadDiagnostics(); radDiagnostics.EmailTo = "support@adambenoit.com"; radDiagnostics.ApplicationName = "PunchClock WP7"; radDiagnostics.ApplicationVersion = "1.0"; radDiagnostics.ExceptionOccurred += new EventHandler<ExceptionOccurredEventArgs>(RadDiagnostics_ExceptionOccurred); radDiagnostics.IncludeScreenshot = true; radDiagnostics.Init(); // Add an Application Bar ApplicationBar = new ApplicationBar(); ApplicationBar.IsMenuEnabled = true; ApplicationBar.IsVisible = true; ApplicationBar.Opacity = 1.0; ApplicationBarIconButton settingButton = new ApplicationBarIconButton(new Uri("/Images/appbar.feature.settings.rest.png", UriKind.Relative)); settingButton.Text = "settings"; settingButton.Click += new EventHandler(settingButton_Click); ApplicationBarIconButton helpButton = new ApplicationBarIconButton(new Uri("/Images/appbar.questionmark.rest.png", UriKind.Relative)); helpButton.Text = "help"; helpButton.Click += new EventHandler(helpButton_Click); ApplicationBar.Buttons.Add(settingButton); ApplicationBar.Buttons.Add(helpButton); } void settingButton_Click(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/Views/Settings.xaml", UriKind.Relative)); } void helpButton_Click(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/Views/Help.xaml", UriKind.Relative)); } private void RadDiagnostics_ExceptionOccurred(object sender, ExceptionOccurredEventArgs e) { //e.Cancel = true; setting Cancel to true will prevent the message box from displaying. } private void DayStartButton_Click(object sender, RoutedEventArgs e) { SendEmail email = new SendEmail(PunchTypes.DayStart); } private void LunchStartButton_Click(object sender, RoutedEventArgs e) { SendEmail email = new SendEmail(PunchTypes.LunchStart); } private void LunchEndButton_Click(object sender, RoutedEventArgs e) { SendEmail email = new SendEmail(PunchTypes.LunchEnd); } private void DayEndButton_Click(object sender, RoutedEventArgs e) { SendEmail email = new SendEmail(PunchTypes.DayEnd); } } }
The second page is the Settings.xaml:
 <phone:PhoneApplicationPage    x:Class="PunchClock.WP7.Views.Settings"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    xmlns:local="clr-namespace:PunchClock.WP7.Business" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"    FontFamily="{StaticResource PhoneFontFamilyNormal}"    FontSize="{StaticResource PhoneFontSizeNormal}"    Foreground="{StaticResource PhoneForegroundBrush}"    SupportedOrientations="Portrait" Orientation="Portrait"    shell:SystemTray.IsVisible="True"> <phone:PhoneApplicationPage.Resources>        <local:AppSettings x:Key="appSettings"></local:AppSettings>    </phone:PhoneApplicationPage.Resources>    <!--LayoutRoot is the root grid where all page content is placed-->    <Grid x:Name="LayoutRoot" Background="Transparent">        <!--Pivot Control-->        <controls:Pivot Title="PUNCHCLOCK">            <!--Pivot item one-->            <controls:PivotItem Header="Addresses">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="addressesStackPanel" Width="420" Height="408">                        <TextBlock Text="Email To" Name="toEmailLabelTextBlock" FontSize="24" Foreground="{StaticResource PhoneAccentBrush}" />                        <TextBlock Text="" Name="toNameTextBlock" FontSize="28" Foreground="{StaticResource PhoneForegroundBrush}" />                        <TextBlock Text="" Name="toEmailTextBlock" FontSize="32" Foreground="{StaticResource PhoneForegroundBrush}" />                        <Button Content="Select a contact" Height="71" Name="selectContactButton" Width="282" Click="selectContactButton_Click" />                    </StackPanel>                </Grid>            </controls:PivotItem>            <!--Pivot item two-->            <controls:PivotItem Header="Subjects">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="subjectsStackPanel" Width="420" Height="408">                        <TextBlock Text="Start Day" Name="dayStartLabelTextBlock" FontSize="24" Foreground="{StaticResource PhoneAccentBrush}" />                        <TextBox HorizontalAlignment="Left" Name="dayStartTextBox" Width="420" />                        <TextBlock Text="Start Lunch" Name="lunchStartLabelTextBlock" FontSize="24" Foreground="{StaticResource PhoneAccentBrush}" />                        <TextBox HorizontalAlignment="Left" Name="lunchStartTextBox" Width="420" />                        <TextBlock Text="End Lunch" Name="lunchEndLabelTextBlock" FontSize="24" Foreground="{StaticResource PhoneAccentBrush}" />                        <TextBox HorizontalAlignment="Left" Name="lunchEndTextBox" Width="420" />                        <TextBlock Text="End Day" Name="dayEndLabelTextBlock" FontSize="24" Foreground="{StaticResource PhoneAccentBrush}" />                        <TextBox HorizontalAlignment="Left" Name="dayEndTextBox" Width="420" />                    </StackPanel>                </Grid>            </controls:PivotItem>        </controls:Pivot>    </Grid> </phone:PhoneApplicationPage>
Settings.xaml.cs
using System; using System.Windows; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; using Microsoft.Phone.Tasks; using PunchClock.WP7.Business; namespace PunchClock.WP7.Views { public partial class Settings : PhoneApplicationPage { public AppSettings settings = new AppSettings(); public Settings() { InitializeComponent(); // Add an Application Bar that has a 'done' confirmation button and // a 'cancel' button ApplicationBar = new ApplicationBar(); ApplicationBar.IsMenuEnabled = true; ApplicationBar.IsVisible = true; ApplicationBar.Opacity = 1.0; ApplicationBarIconButton doneButton = new ApplicationBarIconButton(new Uri("/Images/appbar.check.rest.png", UriKind.Relative)); doneButton.Text = "done"; doneButton.Click += new EventHandler(doneButton_Click); ApplicationBarIconButton cancelButton = new ApplicationBarIconButton(new Uri("/Images/appbar.Close.rest.png", UriKind.Relative)); cancelButton.Text = "cancel"; cancelButton.Click += new EventHandler(cancelButton_Click); ApplicationBar.Buttons.Add(doneButton); ApplicationBar.Buttons.Add(cancelButton); toEmailTextBlock.Text = settings.ToEmailSetting; toNameTextBlock.Text = settings.ToNameSetting; dayStartTextBox.Text = settings.DayStartSetting; lunchStartTextBox.Text = settings.LunchStartSetting; lunchEndTextBox.Text = settings.LunchEndSetting; dayEndTextBox.Text = settings.DayEndSetting; } void doneButton_Click(object sender, EventArgs e) { try { settings.ToEmailSetting = toEmailTextBlock.Text; settings.ToNameSetting = toNameTextBlock.Text; settings.DayStartSetting = dayStartTextBox.Text; settings.LunchStartSetting = lunchStartTextBox.Text; settings.LunchEndSetting = lunchEndTextBox.Text; settings.DayEndSetting = dayEndTextBox.Text; NavigationService.GoBack(); } catch (Exception ex) { MessageBoxResult result = MessageBox.Show( "There was a problem Saving, please try again. If the problem continues, please report the problem by choosing 'Cancel' and saying yes to the next message..", "Error", MessageBoxButton.OKCancel); if (result == MessageBoxResult.Cancel) { throw ex; } else if (result == MessageBoxResult.OK) { } } } void cancelButton_Click(object sender, EventArgs e) { NavigationService.GoBack(); } private void selectContactButton_Click(object sender, EventArgs e) { try { EmailAddressChooserTask emailAddressChooserTask = new EmailAddressChooserTask(); emailAddressChooserTask.Completed += new EventHandler<EmailResult>(emailAddressChooserTask_Completed); emailAddressChooserTask.Show(); } catch (Exception ex) { } } void emailAddressChooserTask_Completed(object sender, EmailResult e) { if (e.TaskResult == TaskResult.OK) { try { toNameTextBlock.Text = e.DisplayName; toEmailTextBlock.Text = e.Email; } catch (Exception ex) { } } } } }
AppSettings.cs
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.IsolatedStorage; namespace PunchClock.WP7.Business {    public class AppSettings    {        // Our isolated storage settings        IsolatedStorageSettings isolatedStore;        // The isolated storage key names of our settings        private const string ToEmailSettingKeyName = "ToEmail";        private const string ToNameSettingKeyName = "ToName";        private const string CcToSelfSettingKeyName = "CcToSelf";        private const string DayStartSettingKeyName = "DayStartSubject";        private const string LunchStartSettingKeyName = "LunchStartSubject";        private const string LunchEndSettingKeyName = "LunchEndSubject";        private const string DayEndSettingKeyName = "DayEndSubject";        // The default value of our settings        private const string ToEmailSettingDefault = "email@example.com";        private const string ToNameSettingDefault = "Default User";        private const bool CcToSelfSettingDefault = true;        private const string DayStartSettingDefault = "Arrival Time";        private const string LunchStartSettingDefault = "Off to lunch";        private const string LunchEndSettingDefault = "Back From Lunch";        private const string DayEndSettingDefault = "Home Time";        /// <summary>        /// Constructor that gets the application settings.        /// </summary>        public AppSettings()        {            try            {                // Get the settings for this application.                isolatedStore = IsolatedStorageSettings.ApplicationSettings;            }            catch (Exception e)            {                Debug.WriteLine("Exception while using IsolatedStorageSettings: " + e.ToString());            }        }        /// <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;            try            {                // if new value is different, set the new value.                if (isolatedStore[Key] != value)                {                    isolatedStore[Key] = value;                    valueChanged = true;                }            }            catch (KeyNotFoundException)            {                isolatedStore.Add(Key, value);                valueChanged = true;            }            catch (ArgumentException)            {                isolatedStore.Add(Key, value);                valueChanged = true;            }            catch (Exception e)            {                Debug.WriteLine("Exception while using IsolatedStorageSettings: " + e.ToString());            }            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="valueType"></typeparam>        /// <param name="Key"></param>        /// <param name="defaultValue"></param>        /// <returns></returns>        public valueType GetValueOrDefault<valueType>(string Key, valueType defaultValue)        {            valueType value;            try            {                value = (valueType)isolatedStore[Key];            }            catch (KeyNotFoundException)            {                value = defaultValue;            }            catch (ArgumentException)            {                value = defaultValue;            }            return value;        }        /// <summary>        /// Save the settings.        /// </summary>        public void Save()        {            isolatedStore.Save();        }        /// <summary>        /// Property to get and set a Username Setting Key.        /// </summary>        public string ToEmailSetting        {            get            {                return GetValueOrDefault<string>(ToEmailSettingKeyName, ToEmailSettingDefault);            }            set            {                AddOrUpdateValue(ToEmailSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a Username Setting Key.        /// </summary>        public string ToNameSetting        {            get            {                return GetValueOrDefault<string>(ToNameSettingKeyName, ToNameSettingDefault);            }            set            {                AddOrUpdateValue(ToNameSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a ListBox Setting Key.        /// </summary>        public string DayStartSetting        {            get            {                return GetValueOrDefault<string>(DayStartSettingKeyName, DayStartSettingDefault);            }            set            {                AddOrUpdateValue(DayStartSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a ListBox Setting Key.        /// </summary>        public string LunchStartSetting        {            get            {                return GetValueOrDefault<string>(LunchStartSettingKeyName, LunchStartSettingDefault);            }            set            {                AddOrUpdateValue(LunchStartSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a ListBox Setting Key.        /// </summary>        public string LunchEndSetting        {            get            {                return GetValueOrDefault<string>(LunchEndSettingKeyName, LunchEndSettingDefault);            }            set            {                AddOrUpdateValue(LunchEndSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a ListBox Setting Key.        /// </summary>        public string DayEndSetting        {            get            {                return GetValueOrDefault<string>(DayEndSettingKeyName, DayEndSettingDefault);            }            set            {                AddOrUpdateValue(DayEndSettingKeyName, value);                Save();            }        }        /// <summary>        /// Property to get and set a ListBox Setting Key.        /// </summary>        public bool CcToSelfSetting        {            get            {                return GetValueOrDefault<bool>(CcToSelfSettingKeyName, CcToSelfSettingDefault);            }            set            {                AddOrUpdateValue(CcToSelfSettingKeyName, value);                Save();            }        }    } }
Here is the Help.xaml file.
<phone:PhoneApplicationPage    x:Class="PunchClock.WP7.Views.Help"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"    xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"    FontFamily="{StaticResource PhoneFontFamilyNormal}"    FontSize="{StaticResource PhoneFontSizeNormal}"    Foreground="{StaticResource PhoneForegroundBrush}"    SupportedOrientations="Portrait" Orientation="Portrait">    <!--LayoutRoot is the root grid where all page content is placed-->    <Grid x:Name="LayoutRoot" Background="Transparent">        <!--Pivot Control-->        <controls:Pivot Title="PunchClock">            <!--Pivot item one-->            <controls:PivotItem Header="about">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="aboutStackPanel" Width="420" Height="612">                        <TextBlock Height="400" Name="textBlock1" Text="PunchClock is an email based application for keeping track of when you arrive to work, take lunch and head home." FontSize="28" TextWrapping="Wrap" />                    </StackPanel>                </Grid>            </controls:PivotItem>            <!--Pivot item one-->            <controls:PivotItem Header="configuration">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="configurationStackPanel" Width="420" Height="612">                        <TextBlock Height="45" Name="textBlock4" Text="1. Open application settings." FontSize="28" TextWrapping="Wrap"/>                        <TextBlock Height="80" Name="textBlock5" Text="2. Select a recipient from your contacts." FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="45" Name="textBlock6" Text="3. Update the email subject lines." FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="45" Name="textBlock7" Text="4. Save the settings." FontSize="28" TextWrapping="Wrap"/>                    </StackPanel>                </Grid>            </controls:PivotItem>            <!--Pivot item one-->            <controls:PivotItem Header="usage">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="usageStackPanel" Width="420" Height="612">                        <TextBlock Height="45" Name="textBlock8" Text="1. Open application settings." FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="80" Name="textBlock9" Text="2. Select a recipient from your contacts." FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="45" Name="textBlock10" Text="3. Update the email subject lines." FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="45" Name="textBlock11" Text="4. Save the settings." FontSize="28" TextWrapping="Wrap"/>                    </StackPanel>                </Grid>            </controls:PivotItem>            <!--Pivot item one-->            <controls:PivotItem Header="support">                <Grid>                    <StackPanel VerticalAlignment="Top" Name="supportStackPanel" Width="420" Height="612">                        <TextBlock Height="80" Name="textBlock12" Text="1. Email support is available from support@adambenoit.com" FontSize="28" TextWrapping="Wrap" />                        <TextBlock Height="80" Name="textBlock13" Text="2. Bug reports and suggestions are always welcome." FontSize="28" TextWrapping="Wrap" />                    </StackPanel>                </Grid>            </controls:PivotItem>        </controls:Pivot>    </Grid> </phone:PhoneApplicationPage>
Email.cs:
using System; using System.Windows; using Microsoft.Phone.Tasks; namespace PunchClock.WP7.Business {    public class SendEmail    {        private readonly AppSettings _settings = new AppSettings();        private readonly EmailComposeTask _emailComposeTask;        public SendEmail(PunchTypes punchType)        {            try            {                _emailComposeTask = new EmailComposeTask();                switch (punchType)                {                    case PunchTypes.DayStart:                        _emailComposeTask.Subject = _settings.DayStartSetting;                        break;                    case PunchTypes.LunchStart:                        _emailComposeTask.Subject = _settings.LunchStartSetting;                        break;                    case PunchTypes.LunchEnd:                        _emailComposeTask.Subject = _settings.LunchEndSetting;                        break;                    case PunchTypes.DayEnd:                        _emailComposeTask.Subject = _settings.DayEndSetting;                        break;                }                _emailComposeTask.To = _settings.ToEmailSetting;                _emailComposeTask.Show();            }            catch(Exception ex)            {                MessageBox.Show("Caught: " + ex.Message);            }        }    }    public enum PunchTypes        {            DayStart,            LunchStart,            LunchEnd,            DayEnd        } }
Comments are closed.