Thursday, March 20, 2014

Visual C# Technical Guru - February 2014

Became the Visual C# Technical Guru for the month of February, 2014.

The TechNet Guru Awards celebrate the technical articles on Microsoft TechNet.

Post in WikiNinjas Official Blog,
http://blogs.technet.com/b/wikininjas/archive/2014/03/17/technet-guru-awards-february-2013.aspx

Untitled
Visual C# Technical Guru - February 2014
Happy Coding.

Regards,
Jaliya

Wednesday, March 19, 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

Monday, March 17, 2014

Portable Code Strategies for Windows Store and Windows Phone 8 App Development : Shared Source Code using “Add As Link” and #if conditional blocks

In this post let’s see how we can use Shared Source Code using “Add As Link” and #if conditional blocks to design a common code base for Windows Store and Windows Phone 8 App development.

I am firing up a new instance of Visual Studio and I am creating a new project. The type of project I am going to create is “Windows Phone App”. I am naming the project as “WindowsPhone8App” and for the solution name I am giving "SharedSourceCodeDemo”. Inside the project I am creating three folders named “Model”, “ViewModel” and “Images”. I am adding some images to the “Images” folder. Inside “Model” folder I am adding a class named “PhotoItem”.

PhotoItem.cs
using System;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
 
namespace WindowsPhone8App.Model
{
    public class PhotoItem
    {
        public string PhotoName { get; set; }
        public BitmapImage Photo { get; set; }
 
        public static List<PhotoItem> GetPhotos()
        {
            return new List<PhotoItem>()
            {
                new PhotoItem(){PhotoName="Image1",Photo = new BitmapImage(new Uri("/Images/Image1.jpg", UriKind.Relative))},
                new PhotoItem(){PhotoName="Image2",Photo = new BitmapImage(new Uri("/Images/Image2.jpg", UriKind.Relative))},
            };
        }
    }
}
Inside “ViewModel” folder, I am adding a class named “PhotoItemViewModel”.

PhotoItemViewModel.cs
using WindowsPhone8App.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
 
namespace WindowsPhone8App.ViewModel
{
    public class PhotoItemViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<PhotoItem> photoList;
        public ObservableCollection<PhotoItem> PhotoList
        {
            get
            {
                return photoList;
            }
            set
            {
                photoList = value;
                NotifyPropertyChanged();
            }
        }
 
        public void LoadData()
        {
            PhotoList = new ObservableCollection<PhotoItem>(PhotoItem.GetPhotos());
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
Now inside my MainPage.xaml I have the following design.

MainPage.xaml
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <phone:LongListSelector ItemsSource="{Binding PhotoList}">
        <phone:LongListSelector.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding PhotoName}"></TextBlock>
                    <Image Source="{Binding Photo}"></Image>
                </StackPanel>
            </DataTemplate>
        </phone:LongListSelector.ItemTemplate>
    </phone:LongListSelector>
</Grid>
Now inside my MainPage.xaml.cs I have the following code.

MainPage.xaml.cs
using System.Windows;
using Microsoft.Phone.Controls;
using WindowsPhone8App.ViewModel; 

namespace WindowsPhone8App
{
    public partial class MainPage : PhoneApplicationPage
    {
        PhotoItemViewModel viewModel = new PhotoItemViewModel();
 
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }
 
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            viewModel.LoadData();
            DataContext = viewModel;
        }
    }
}
Now when I run the app, it is working as expected.

Picture1
Windows Phone 8
Now let’s see how we can use the above two classes in a Windows Store App and that's of course without copy and pasting the files across the projects.

I am adding a new project to the solution of type “Blank App(XAML)” under Windows Store App templates which I am naming as “WindowsStoreApp”. There I am creating three folders named “Model”, “ViewModel” and “Images”. Now I am right clicking on the Model and clicking on Add->Existing Item. I am navigating to the “WindowsPhone8App” projects’ model folder and selecting the “PhotoItem.cs”. Instead of clicking on “Add”, I am selecting “Add As Link.”

Untitled
"Add As Link"
I am doing the same for “PhotoItemViewModel.cs” and for my Images. I am adding all these as “Add As Link” to respective folders.

Now I can see my project files in the Solution Explorer as follows.

Picture1
Files added" using "Add As Link"
Now when I open the “PhotoItem.cs” from my “WindowsStoreApp” project, I am getting some errors.

Untitled
Error
That is of course I can’t use Windows Phone 8 Assemblies inside my Windows Store Application. For that I am going to use #if conditional blocks. I can find the compilation symbol for Windows Store Apps in project properties. Inside Build tab, there it is as "NETFX_CORE". Same way you can find the compilation symbol for Windows Phone 8 apps which is "WINDOWS_PHONE"

Picture1
Conditional compilation symbols
Now I am modifying the "PhotoItem" class as follows.

PhotoItem.cs
using System;
using System.Collections.Generic; 

#if NETFX_CORE
using Windows.UI.Xaml.Media.Imaging;
#endif
 
#if WINDOWS_PHONE
using System.Windows.Media.Imaging;
#endif
 
namespace WindowsPhone8App.Model
{
    public class PhotoItem
    {
        public string PhotoName { get; set; }
 
#if NETFX_CORE
        public string Photo { get; set; }
 
        public static List<PhotoItem> GetPhotos()
        {
            return new List<PhotoItem>()
            {
                new PhotoItem(){PhotoName="Image1",Photo = "/Images/Image1.jpg"},
                new PhotoItem(){PhotoName="Image2",Photo = "/Images/Image2.jpg"},
            };
        }
#endif
 
#if WINDOWS_PHONE
        public BitmapImage Photo { get; set; }
 
        public static List<PhotoItem> GetPhotos()
        {
            return new List<PhotoItem>()
            {
                new PhotoItem(){PhotoName="Image1",Photo = new BitmapImage(new Uri("/Images/Image1.jpg", UriKind.Relative))},
                new PhotoItem(){PhotoName="Image2",Photo = new BitmapImage(new Uri("/Images/Image2.jpg", UriKind.Relative))},
            };
        }
#endif
    }
}
Here I have inserted some #if conditional blocks for using statements as well as inside the class. That’s because in Windows Store App, I can’t directly bind image to a BitmapImage, instead I need to set the Image source Uri as a string. The thing to understand here is there is only one PhotoItem class, I am using #if conditional blocks to state which part I am going to use in Windows Store App and which part I am going to use in Windows Phone 8 App.

Now once this is done, I am modifying the MainPage.xaml inside my Windows Store App to bind to “PhotoItemViewModel”.

MainPage.xaml
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{Binding PhotoList}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding PhotoName}"></TextBlock>
                    <Image Source="{Binding Photo}" Width="100" Height="100"></Image>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
MainPage.xaml .cs
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using WindowsPhone8App.ViewModel;
 
namespace WindowsStoreApp
{
    public sealed partial class MainPage : Page
    {
        PhotoItemViewModel viewModel = new PhotoItemViewModel();
 
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }
 
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            viewModel.LoadData();
            DataContext = viewModel;
        }
    }
}
After completing all these steps, I am running my Windows Store App. I am getting the output as follows.
Picture1
Windows Store App
I am uploading the sample to my SkyDrive, enjoy!


Happy Coding.

Regards,
Jaliya