Tuesday, March 18, 2014

Portable Code Strategies for Windows Store and Windows Phone 8 App Development : Partial Classes

In this post let’s see how we can use partial classes to design a common code base for Windows Store and Windows Phone 8 App development. Before that, let's have a quick introduction on Partial Classes.

Partial Classes

Partial key word on a class let you have two classes within the same namespace with a same class name. (Using Partial key word, it is possible to split the definition of a class or a struct, an interface or a method over two or more source files). When the application is compiling. both these classes joins together and will be compiled as one single class. Partial classes are mostly used to separate commonly-edited code from rarely-edited code. Best example would be when you create a Windows Forms application using Visual Studio you can see two files "Form1.cs" and "Form1.designer.cs". Though there are two physical files, both of these represent a single class named "Form1".

Moving back to the topic, Let’s say I want to access device information from my Windows Phone 8 and Windows Store App. In Windows Phone 8 App, it will be Windows Phones device information and in Windows Store App, it can be PC/Tablet etc. device information. The thing to note here is I can’t use the same APIs or libraries to access device information in different platforms. But inside my ViewModel or where ever I am accessing the device information, my code should be same regardless of the platform and that’s the core concept behind “Build for Both”. Now let’s see this in action.

I opening up Visual Studio and I am creating a new project. The type of project I am going to create is “Windows Phone App” and I am naming the project as “WindowsPhone8App” and for the solution name I am giving "PartialClassDemo”. When the project is created, I am adding a new class named “DeviceInfo” and I am modifying it with the partial keyword.

DeviceInfo.cs
namespace Common
{
    public partial class DeviceInfo
    {
        private static DeviceInfo _default;
        public static DeviceInfo Default
        {
            get
            {
                if (_default == null)
                {
                    _default = new DeviceInfo();
                }
                return _default;
            }
        }
    }
}
In above class I don’t have any using statements and I should be able to use the above class in a Windows Store application without doing any modification.

Now I am adding a another class named “DeviceInfo_WP8” and I am modifying it with the partial keyword and changing the class name into “DeviceInfo”. There I am writing the Windows Phone 8 platform specific code.

DeviceInfo_WP8.cs
using Microsoft.Phone.Info;
using System;
 
namespace Common
{
    public partial class DeviceInfo
    {
        private string deviceId;
        public string DeviceId
        {
            get
            { 
                object value;
                if(DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out value))
                {
                    deviceId = Convert.ToBase64String(value as byte[]);
                }
                return deviceId;
            }
        }
     }
}
Now for the demonstration purposes in the MainPage.xaml, I have a textblock and in the Loaded event, I am writing the following.

MainPage.xaml.cs
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
   txtDeviceId.Text = DeviceInfo.Default.DeviceId;
}
Now when I run the Windows Phone 8 application, I am getting the desired output.
Picture1
Windows Phone 8 Result
One of the important things to note here is, to access device id from a Windows Phone, you need to tick "ID_CAP_IDENTITY_DEVICE" capability in Windows Phone 8 projects' WMAppManifest.xml file.

ID_CAP_IDENTITY_DEVICE in WMAppManifest.xml
Now let’s add a Blank Windows Store App to the solution. There first what I am going to do is I am right clicking on the project and clicking on Add->Existing Item. I am navigating to the “WindowsPhone8App” projects’ folder and selecting the “DeviceInfo.cs”. Instead of clicking on “Add”, I am selecting “Add As Link.”

Untitled
"Add As Link"
Now I am adding a new class to the project named “DeviceInfo_Windows” and I am modifying it with the partial keyword and changing the class name to “DeviceInfo”. There I am writing the Windows 8 platform specific code.

DeviceInfo_Windows.cs
using System;
using Windows.Storage.Streams;
using Windows.System.Profile;

namespace Common
{
    public partial class DeviceInfo
    {
        private string deviceId;
        public string DeviceId
        {
            get
            {
                if (deviceId == null)
                {
                    IBuffer hardwareId = HardwareIdentification.GetPackageSpecificToken(null).Id;
                    DataReader reader = DataReader.FromBuffer(hardwareId);
                    byte[] bytes = new byte[hardwareId.Length];
                    reader.ReadBytes(bytes);
                    deviceId = BitConverter.ToString(bytes);
                }
                return deviceId;
            }
        }
    }
}
Now I am all done. Inside the MainPage.xaml, I have added a textblock and in the Loaded event, I am writing the same code which I used in Windows Phone 8 App.

ManPage.xaml.cs
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    txtDeviceId.Text = DeviceInfo.Default.DeviceId;
}
Now when I run the Windows Store App, I am getting the following result.

Picture1
Windows Store App
I am uploading the sample to my SkyDrive, enjoy!


Happy Coding.

Regards,
Jaliya