Windows Phone 8 shared core with Windows 8 – File IO

For developers, the biggest news for Windows Phone 8 is that it shares a core with Windows 8. It means that your code has more chances than ever before to be compatible on both platforms.

One of the easier components and surely the most used in applications is the File IO component. In this post, I’ll also cover the Windows Phone 7 code compatibility.

In Windows Phone 7

To write a file, you use the IsolatedStorageFile:

private void WriteFile(string fileName, string content)
{
    using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream isolatedStorageFileStream = isolatedStorageFile.CreateFile(fileName))
        {
            using (StreamWriter streamWriter = new StreamWriter(isolatedStorageFileStream))
            {
                streamWriter.Write(content);
            }
        }
    }
}

To read a file:

private string ReadFile(string fileName)
{
    string text;

    using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream isolatedStorageFileStream = isolatedStorageFile.OpenFile(fileName, FileMode.Open))
        {
            using (StreamReader streamReader = new StreamReader(isolatedStorageFileStream))
            {
                text = streamReader.ReadToEnd();
            }
        }
    }

    return text;
}

In Windows Phone 8

To write a file, you use the Windows.Storage component. The file and folder objects are respectively IStorageFile and IStorageFolder. The usage of the await and async keywords come in.

To write a file:

public async Task WriteFile(string fileName, string text)
{
    IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;

    IStorageFile storageFile = await applicationFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

    using (Stream stream = await storageFile.OpenStreamForWriteAsync())
    {
        byte[] content = Encoding.UTF8.GetBytes(text);
        await stream.WriteAsync(content, 0, content.Length);
    }
}

To read a file:

public async Task<string> ReadFile(string fileName)
{
    string text;
    IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;

    IStorageFile storageFile = await applicationFolder.GetFileAsync(fileName);

    IRandomAccessStream accessStream = await storageFile.OpenReadAsync();

    using (Stream stream = accessStream.AsStreamForRead((int)accessStream.Size))
    {
        byte[] content = new byte[stream.Length];
        await stream.ReadAsync(content, 0, (int) stream.Length);

        text = Encoding.UTF8.GetString(content, 0, content.Length);
    }

    return text;
}

You can use these methods this way:

await WriteFile("Dummy.txt", "I love the Windows Phone");
string text = await ReadFile("Dummy.txt");

You can see that the code between Windows Phone 7 and Windows Phone 8 is quite different.

Compatibility

As we know already, Microsoft announced that the Windows Phone 7 applications will run on Windows Phone 8. This is great news. What is even better is that your Windows Phone 7 code that uses the IsolatedStorage will compile without any changes in Windows Phone 8. You can take the Windows Phone 7 code above and it will work.

You might be wondering if the internal folder structure is different between WP7 and WP8… The difference is minor.

In WP7, if you create a file at the root, the file will point to:

C:DataUsersDefaultAppAccountAppData{9679D8C4-24B4-41DF-85C5-5E099947F109}LocalIsolatedStoreDummy.txt

In WP8, the same file created at the root will be in:

C:DataUsersDefaultAppAccountAppData{9679D8C4-24B4-41DF-85C5-5E099947F109}LocalDummy.txt

The difference is the IsolatedStore folder added in WP7. It means that if you have old WP7 code that you would like to use with new WP8 code, you just have to get the IsolatedStore folder:

IStorageFolder applicationFolder = 
    await ApplicationData.Current.LocalFolder.GetFolderAsync("IsolatedStore");

In the end, you can mix both WP7 and WP8 code in your next Windows Phone 8 application. However, I would encourage you to use only the Windows Phone 8 version, as it will then be easier for you to use the same code in Windows 8.

Windows Phone 8 Battery API

The Battery API makes a nice addition to the WP8 SDK.

I can see in the near future that some applications will display the battery metrics on a Live Tile or in the application that hides the System Tray.

The Battery API is pretty easy to use:
1- Get the Battery instance with Battery.GetDefault().
2- Bind to the event RemainingChargePercentChanged.

The battery properties are:
RemainingChargePercent: gets a value that indicates the percentage of the charge remaining on the phone’s battery.
RemainingDischargeTime: gets a value that estimates how much time is left until the phone’s battery is fully discharged. 

With the following code:

using Windows.Phone.Devices.Power;

namespace BatteryApp
{
    public partial class MainPage
    {
        private readonly Battery _battery;

        public MainPage()
        {
            InitializeComponent();

            _battery = Battery.GetDefault();

            _battery.RemainingChargePercentChanged += OnRemainingChargePercentChanged;

            UpdateUI();
        }

        private void OnRemainingChargePercentChanged(object sender, object e)
        {
            UpdateUI();
        }

        private void UpdateUI()
        {
            textBlockRemainingCharge.Text = string.Format("{0} %", _battery.RemainingChargePercent);
            textBlockDischargeTime.Text = string.Format("{0} minutes", _battery.RemainingDischargeTime.TotalMinutes);
        }
    }
}

You get:

image


Please note that when running this on the emulator, it will show 100% and an infinite discharge time. The above values are fake.

Get ready to code!

Windows Phone 8 upcoming Live Tile feature

With all the buzz this week about the Windows Phone 8 SDK leak, I couldn’t resist installing it.

The title of the SDK is Windows Phone 8 Developer Preview. There are so many cool new features that initially, I didn’t know where to start. I decided to start with one of the new features of the live tiles, since this is the Windows Phone’s biggest strength.

I don’t know the exact feature name, but it’s about cycling images in a live tile. Here is a little video that will help to describe the feature.

Cycling images in a Live Tile

Have you spotted the difference between the Windows Phone 7 badge count and the new OS? It is now in a square instead of a circle!

What I love about Microsoft is that they make it easy for developers to use their APIs.

Follow these two steps to accomplish what you see in the video:
1- Add up to 9 images to the project and set the Build Action to Content. The images need to be local only.
2- Append the following code

ShellTile appTile = ShellTile.ActiveTiles.First();

if (appTile != null)
{
    Uri uri1 = new Uri("/Assets/UltimatePokerManager.png", UriKind.Relative);
    Uri uri2 = new Uri("/Assets/YourShape.png", UriKind.Relative);

    CycleTileData cycleTileData = new CycleTileData
                                        {
                                            Count = 3, 
                                            CycleImages = new[] {uri1, uri2}
                                        };

    appTile.Update(cycleTileData);
}

The UtimatePokerManger.png and YourShape.png have the size 173×173. When you watched the video, the images were expanded.

Please note that the SDK is in preview and there is no guarantee that the APIs will be the same in the released version, but I bet this feature will stay as it is.

This was my first Windows Phone 8 blog post and is surely not the last!

How to backup your Windows Phone app data to a server such as GoDaddy

Here is a complete step-by-step guide to create a WCF backup service for your Windows Phone applications.

You can implement your own hosting service with a cheap hosting server like GoDaddy. You can find deal at $5/month. Personally, I find it more professional saving your application data to a private server or in a cloud solution instead of relaying on SkyDrive.

To accomplish this, two things are required:
A- Implementing the service on your server.
B- Implementing the client code to send your data.

Alternatively, you can download the complete solution at the end of the article.

A) Server side

1- Let’s start with the hardest part. After you find a hosting server that supports the framework .NET 4.0, you create the WCF Service Application:

image

2- Rename the file IService1.cs to IFileUploader.cs

3- Replace the content of the IFileUploader.cs with:

using System.Runtime.Serialization;
using System.ServiceModel;

namespace FileUploadService
{
    [ServiceContract]
    public interface IFileUploader
    {
        // Returns null when there is no error, otherwise it is the exception message.
        [OperationContract]
        string Upload(UploadFile uploadFile);
    }

    [DataContract]
    public class UploadFile
    {
        // Don't forget to set the variable FileUploadDirectoryWithReadWritePermission in your Web.config and set read/write permission in your web hosting.
        // RelativeDirectory should be in the form as /Path1/Path2/ or null for the root directory.
        [DataMember]
        public string RelativeDirectory { get; set; }

        [DataMember]
        public string FileName { get; set; }

        [DataMember]
        public byte[] Content { get; set; }
    }
}

This interface contains only the Upload method. The Upload needs a UploadFile which contains only 3 properties: RelativeDirectory, FileName and Content.

4- Rename the file Service1.svc to FileUploader.svc.

5- Replace the content of FileUploader.svc with:

using System;
using System.Configuration;
using System.IO;
using System.Web.Hosting;

namespace FileUploadService
{
    public class FileUploader : IFileUploader
    {
        #region IFileUploader Members

        public string Upload(UploadFile uploadFile)
        {
            string message = null;

            try
            {
                string path = HostingEnvironment.MapPath(string.Format("~/{0}",ConfigurationManager.AppSettings["FileUploadDirectoryWithReadWritePermission"]));
                
                if (path != null)
                {
                    if (uploadFile.RelativeDirectory != null && uploadFile.RelativeDirectory.StartsWith("/"))
                    {
                        path = string.Concat(path, uploadFile.RelativeDirectory);
                    }

                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    if (!string.IsNullOrEmpty(uploadFile.FileName))
                    {
                        using (FileStream fileStream = File.Open(Path.Combine(path, uploadFile.FileName), FileMode.Create))
                        {
                            using (var binaryWriter = new BinaryWriter(fileStream))
                            {
                                binaryWriter.Write(uploadFile.Content);
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                message = exception.Message;
            }

            return message;
        }

        #endregion
    }
}

6- Replace the content of the Web.config with:

<?xml version="1.0"?>

<configuration>

  <appSettings>
    <add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <customErrors mode="Off" />
  </system.web>

  <system.serviceModel>

    <behaviors>
      <serviceBehaviors>
        <behavior name="FileUploadBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      <service behaviorConfiguration="FileUploadBehavior" name="FileUploadService.FileUploader">
        <endpoint address="" name="basicHttpStream" binding="basicHttpBinding"
                  bindingConfiguration="httpLargeMessageStream" contract="FileUploadService.IFileUploader" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
      <basicHttpBinding>
        <binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
                 name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </basicHttpBinding>
    </bindings>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

</configuration>

This file has two important sections:

– The parameter FileUploadDirectoryWithReadWritePermission is used by the file FileUploader.svc and it will be used in your public folder later.

  <appSettings>
    <add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
  </appSettings>

– The section about the length of the service parameters: You don’t need to understand everything here. It just works as is. If you are curious, I invite you to read the documentation on MSDN.

<bindings>
      <basicHttpBinding>
        <binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
                 name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </basicHttpBinding>
    </bindings>

7- The service is ready to be published. Right-click on the FileUploadService project and choose Publish. Depending on your web hosting service, you need to set the info.

For GoDaddy:

– Use the FTP method.

– Set the target location. For me, I used ftp://ftp.ultimatepokermanager.com/upm/ServerTest

– Set the credentials 

image

8- The trickiest part is to configure the application settings for the WCF service in the hosting service. In GoDaddy, it’s in the IIS Management in the Tools section. You need to check Anonymous Access and Set Application Root.

The upmservertest points to http://www.ultimatepokermanager.com/upm/servertest

image

8- To check if your service is running, open your browser and put the address of the web service. With my web service, the address is:

http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc

If you see something like the following image, you’re good to go!

image

B) Client side

I created a simple application that sends a string into a file in the server.

image

1- Create a Windows Phone Application. I assume that you know how to do this step.

2- The WCF service client FileUploader needs to be added to the project. Right-click on the Windows Phone project and click on Add Service Reference.

image

– Put the address of your WCF service. In this example, it is http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc 
– Rename the namespace to FileUploader.

– Click OK.

3- Replace the content of the MainPage.xaml with:

<phone:PhoneApplicationPage x:Class="SendFileApp.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"
                            mc:Ignorable="d"
                            d:DesignWidth="480"
                            d:DesignHeight="800"
                            FontFamily="{StaticResource PhoneFontFamilyNormal}"
                            FontSize="{StaticResource PhoneFontSizeNormal}"
                            Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Margin="12,17,0,28">

            <TextBlock Text="SEND FILE"
                       Style="{StaticResource PhoneTextNormalStyle}" />

            <TextBlock Text="dashboard"
                       Margin="9,-7,0,0"
                       Style="{StaticResource PhoneTextTitle1Style}" />

        </StackPanel>

        <StackPanel Grid.Row="1"
                    Margin="12,0,12,0">

            <TextBlock Margin="12,0,0,0"
                       Text="Content" />

            <TextBox Text="abcdefg"
                     x:Name="textBoxContent" />

            <TextBlock Margin="12,0,0,0"
                       Text="File name" />

            <TextBox Text="Sample.txt"
                     x:Name="textBoxFileName" />

            <Button Content="Send File"
                    Click="ButtonSendFile" />

            <Button Content="Download File"
                    Click="ButtonDownloadFile"
                    IsEnabled="False"
                    x:Name="buttonDownloadFile"/>

        </StackPanel>

    </Grid>

</phone:PhoneApplicationPage>

This content uses only standard controls.

4- Replace the content of MainPage.xaml.cs with:

using System;
using System.Net;
using System.Text;
using System.Windows;
using SendFileApp.FileUploader;

namespace SendFileApp
{
    public partial class MainPage
    {
        #region Constants

        // For this sample, the uploaded file can be access from my public folder
        private const string PublicServer = "http://www.ultimatepokermanager.com/upm/ServerTest/backup";

        #endregion

        #region Fields

        private string _directory;

        #endregion

        #region Constructor

        public MainPage()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        private void ButtonSendFile(object sender, RoutedEventArgs e)
        {
            byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
            _directory = Guid.NewGuid().ToString();

            FileUploaderClient fileUploaderClient = new FileUploaderClient();
            fileUploaderClient.UploadCompleted += UploadCompleted;
            
            fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
        }

        private void UploadCompleted(object sender, UploadCompletedEventArgs uploadCompletedEventArgs)
        {
            buttonDownloadFile.IsEnabled = true;

            if (uploadCompletedEventArgs.Result == null)
            {
                MessageBox.Show("The file has been successfully uploaded.", "Success!", MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show(string.Format("An error occured:nn{0}", uploadCompletedEventArgs.Result), "Error", MessageBoxButton.OK);
            }
        }

        private void ButtonDownloadFile(object sender, RoutedEventArgs e)
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += WebClientDownloadStringCompleted;

            webClient.DownloadStringAsync(new Uri(string.Format("{0}/{1}/{2}", PublicServer, _directory, textBoxFileName.Text)));
        }

        private void WebClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs downloadStringCompletedEventArgs)
        {
            if (downloadStringCompletedEventArgs.Error == null)
            {
                MessageBox.Show(string.Format("The content of your file is:nn{0}", downloadStringCompletedEventArgs.Result), "Success!", MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show(string.Format("An error occured:n{0}", downloadStringCompletedEventArgs.Error), "Error", MessageBoxButton.OK);
            }
        }

        #endregion
    }
}

The interesting part in the previous code is:

private void ButtonSendFile(object sender, RoutedEventArgs e)
{
    byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
    _directory = Guid.NewGuid().ToString();

    FileUploaderClient fileUploaderClient = new FileUploaderClient();
    fileUploaderClient.UploadCompleted += UploadCompleted;
    
    fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
}

The usage of the FileUploaderClient is really simple:

1- Create the instance FileUploaderClient.

2- Listen to the UploadCompleted event.

3- Upload the file asynchronously.

Please note that the UploadFile needs the properties RelativeDirectory (which starts with a “/”), a FileName and the Content in an array of bytes.

An example of an uploaded file address is: http://www.ultimatepokermanager.com/upm/ServerTest/backup/a5a8ae0b-50f0-4d16-90da-e83d6e1d30a3/Sample.txt. You can see the backup directory previously set in the Web.config file.

In the sample, I generated a GUID for the directory name. Also, the uploaded files are public as long as the user (or the application) knows about the directory name and the file name. If you want to add a layer of privacy, you just have to implement a DownloadFile method into your service. It should not be difficult if you read the code of the Upload method.

I guarantee you that you’ll be happy to see when your web service is working!

Download Sample project

Book Review: Windows Phone 7.5 Unleashed

In the past year and a half, I have read a lot of Windows Phone books. The first book I read was the excellent 101 Windows Phone 7 apps. At that time, I was recommended that book, but ever since Microsoft released the Mango update, 101 is a bit out of date.

At the end of 2011, I read Essential Windows Phone 7.5 by Shawn Wildermuth. I recommend this book for someone who has never owned a Windows Phone and who wants to start programming for the Windows Phone. It is an excellent book for beginners, as the author spends time about on basic Windows Phone concepts.

Now to my review of the latest Windows Phone book I have read: Windows Phone 7.5 Unleashed by Daniel Vaughan.

WP7U

This book is huge with 1120 pages, and all of them are worth it. Here are some of the things that I like about the book:

  • Most of the code samples are done with the MVVM pattern. Nowadays, this pattern is the most popular one used when creating Windows Phone applications. The author even shares his known Calcium SDK that includes the MVVM philosophy. For a beginner who wants to start Windows Phone programming, starting off with the best pattern is a great idea, and this book will help you do that.
  • There is a lot of free code given. There are a lot of utility classes that can be used in many types of Windows Phone applications. Honestly, the book is worth buying for the free code alone, and it will save you a lot of time.
  • If you are new to use the SQL Compact Server database, this book will help you to learn the technology; the author has a large helpful section on this topic.
  • The author introduced the usage of Reactive Extensions. This technology is not for beginners, but I’m pretty sure it will intrigue you, as it did me. The author presents the benefits of Reactive Extensions. The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. You can find the rest of the definition at the official website.
  • The author knows the platform well and describes many useful hints and caveats in Windows Phone programming.

In conclusion, this excellent book is one that I recommend right now if you want to dive into Windows Phone programming or to learn more about the recent features added with Mango.

Happy reading!

Application name matters

If you are developing an application for your company with a brand name or if you are developing the next Angry Bird game with a cool new name, this post is not for you.

However, if you are concocting a generic application like a calculator, a converter, a task manager, you might want continuing to read this post.

Last year, I released the Ultimate Poker Manager along with the ad based version Ultimate Poker Manager Free. Those apps are a poker timer, a hand reference helper and a statistic manager that can produce a whole website with game results and a leaderboard. After a couple of months, I realized that my apps were not gaining traction as much as simple apps like Poker Timer or Poker Hands even if my app was more appealing.

With these results, I tried to rebrand the app for Poker Hands & Timer and I added it to the marketplace (only as a free app). I kept the old Ultimate Poker Manager Free in order to be able update the users that installed my app.

After one and half year, I can tell you that the Poker Hands & Timer has been downloaded twice as much as the Ultimate Poker Manager Free. My download count is in thousands.

I do believe that the marketplace search algorithm put a lot of weight on application name first. So in the end, don’t look for fancy names, keep it simple!

This post is not based on exact science but on my experience. If you agree or not, please feel free to comment.

Windows Phone 7 App Hub VS Windows 8 Dashboard

This week, Microsoft presented what I believe are the best announcements in the last 10 years: the coming release of the gorgeous Surface and the next Windows Phone 8 OS.

I was ready to blog about the new SDK of Windows Phone 8, but we have to wait until the SDK is released. However, we should be pleased that the core of Windows Phone 8 and Windows 8 will be the same.

Back to the blog post now!

Microsoft is serious about Windows 8. They ran a lot of interesting events for the developers. I must admit that living in a big city helps. Recently, I participated in the App Excellence Lab for Windows 8 where I was given early access to the Windows 8 Dashboard. I presented my port of my Windows Phone Canadian Developer Connection app to Windows 8. In a future blog post, I’ll talk about my experience porting an application from Windows Phone 7 to Windows 8.

For developers that submitted Windows Phone 7 applications, you will have dealt with the App Hub many times and you have probably seen some hiccups. Fortunately, the Windows Phone team gave the developers good news about the upcoming upgrade of the App Hub.

Right now, the Windows 8 Dashboard (that’s the current name) does not share the same system as the App Hub. In a couple of years, they might share a dashboard, but for now I’ll present some differences.

Dashboard

image

Submit an app

All the steps are well defined and you get the approximate time for each step.

image

Explore store trends

This is what I consider the best tool of the Windows 8 Dashboard. It gives you the ability to analyze what people install on Windows 8. I hope this feature will soon come to the App Hub.

image

Financial summary

This is the place where you find out if you’ll be millionaire one day.

image

Profile Account

I skipped the section Renewal, there was nothing interesting. The Profile Account is pretty normal except that you can change the Publisher name.

image

Microsoft Support

This is the second major feature of the Windows 8 Dashboard. Recently, I had a question to ask the certification team and I visited the support page. I was expecting to fill in a form and get an answer one or two days later like it is in the App Hub, but I was totally surprised that the Dashboard offers you the possibility of chatting with a support representative during the week days. I picked this option and 2 seconds later, I was chatting. I hope this wait time will stay the same!

image

Now, go back to your code and port all your beautiful Windows Phone apps to Windows 8!

Security helper class that encrypt/decrypt settings and files

Even though the Windows Phone platform is more secure than either iOS or Android, it is always good practice to encrypt sensitive data.

I created a small SecurityHelper class that handles the encryption and the decryption of application settings and files.

The usage of the class is easy as:

SecurityHelper.WriteSetting("Username", "Sébastien");

string username = SecurityHelper.ReadSetting("Username");

The complete usage is described in the following sample code (which is also available in the downloadable Sample project below):

using System.Diagnostics;
using DotNetApp;

namespace SecurityHelperApp
{
    public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();

            // Write and read an ApplicationSetting into the IsolatedStorageSettings
            WriteReadSettingExample();

            // Write and read a file with the specified string content
            WriteReadFileWithStringContentExample();

            // Write and read a file in a sub folder with the specified string content
            WriteReadFileInSubFolderWithStringContentExample();

            // Write and read a file with the specified bytes content
            WriteReadFileWithByteContentExample();
        }

        #region Private Methods

        private void WriteReadSettingExample()
        {
            SecurityHelper.WriteSetting("Username", "Sébastien");

            string username = SecurityHelper.ReadSetting("Username");

            Debug.Assert(username == "Sébastien");
        }

        private void WriteReadFileWithStringContentExample()
        {
            SecurityHelper.WriteFile("File1.txt", "I love Windows Phone");

            string content = SecurityHelper.ReadFile("File1.txt");

            Debug.Assert(content == "I love Windows Phone");
        }

        private void WriteReadFileInSubFolderWithStringContentExample()
        {
            SecurityHelper.WriteFile("Metro/SubFolder/File3.txt", "I love the Metro design");

            string content = SecurityHelper.ReadFile("Metro/SubFolder/File3.txt");

            Debug.Assert(content == "I love the Metro design");
        }

        private void WriteReadFileWithByteContentExample()
        {
            byte[] content = new byte[] {1, 2, 3, 4, 5};
            SecurityHelper.WriteFile("File2.txt", content);

            byte[] readContent;
            SecurityHelper.ReadFile("File2.txt", out readContent);

            Debug.Assert(content[0] == readContent[0] && content[1] == readContent[1] && content[2] == readContent[2] && 
                content[3] == readContent[3] && content[4] == readContent[4]);
        }

        #endregion
    }
}

Download SecurityHelper
Download Sample project

How to create a spinner control

Most of the commercial components of Windows Phone contain a spinner control. However, if you can afford to buy a licence, you can use the one I provide below.

Here is a screenshot:

Spinner

To include the SpinnerControl in your project, you need to:

1- Unzip SpinnerControl.zip.
2- Add the three unzipped files to your project in the root.
3- Set the build action of the Spinner.png to Content
4- Add the SpinnerControl XAML code.

If you look at my sample project, which is an empty Windows Phone application (see download link at end of blog post), you will see:

    <DotNetApp:SpinnerControl Grid.RowSpan="2"
                              IsSpinning="True"
                              Status="Loading..."
                              VerticalAlignment="Center"
                              x:Name="spinner"/>

The simple SpinnerControl that I provide contains only 2 bindable properties:

IsSpinning: When it is set to true, the spinner rotates and it is visible. When it is set to false, the control is collapsed.

Status: This property is optional and it is used to put text under the spinner. It is useful if you wish to display the progress.

If we look at the file in more detail, SpinnerControl.xaml has is two important parts:

1- The Storyboard to rotate the image

    <Storyboard x:Name="StoryBoardAnimateSpinner">

      <DoubleAnimation AutoReverse="False"
                       Duration="0:0:2"
                       From="0"
                       RepeatBehavior="Forever"
                       Storyboard.TargetName="SpinnerTransform"
                       Storyboard.TargetProperty="Angle"
                       To="360" />

    </Storyboard>

This storyboard can be translated to: The image will rotate through 360 degrees every two seconds at a constant rate of rotation, and will continue to rotate forever. If you wish, you can set it to rotate through 360 degrees at a different speed, for example, every five seconds instead of every two seconds. You simply need to modify the Duration property.

2- The Image

    <Image Height="50"
           Margin="10,10"
           Source="/Spinner.png"
           Stretch="Uniform"
           Width="50"
           x:Name="spinImage">

      <Image.RenderTransform>

        <RotateTransform x:Name="SpinnerTransform"
                         CenterX="25"
                         CenterY="25" />

      </Image.RenderTransform>

    </Image>

The Height and Width of spin image need to be equal, otherwise, you’ll get a weird rotation. The CenterX and CenterY need to be half the value of the Height (or Width). The image Spinner.png that I provided in the SpinnerControl is 40 x 40, but in the above code, I specified 50 x 50 and I made sure to set the Stretch property to Uniform.

The other control in the SpinnerControl is a TextBlock which you probably know. You can configure it with your own values and you can even add dependency properties to the control to make it more general.

Download SpinnerControl
Download Sample project

Running two emulators can help to design and debug

Recently, I discovered involuntarily that it is possible to run simultaneously the Windows Phone Emulator 512 MB and the Windows Phone Emulator 256 MB at the same time.

image

While tweaking and adjusting the user interface, having both emulators side-by-side can help you compare your changes.

Make sure you download the Windows Phone SDK 7.1.1. As a reminder, it is always a best practice to test if your application can run on a 256 MB device.

After installing the Windows Phone SDK 7.1.1, you’ll have this selection of emulators:

image

1- Start debugging with the 512 MB emulator.
2- Stop debugging.
3- Select the 256 MB emulator and start debugging.
4- Now, you can start manually your application on the 512 MB emulator.