I recently talked about Cross Platform Development Options in Windows 8 and Windows Phone 8

In this blog post I describe how you can achieve Cross-Platform development across Windows 8 and Windows Phone 8 specifically using C# + XAML. We will be developing a simple Calculator App for both the platforms with common library and minimum platform specific layer. The key is to use "Portable Class Library" template.

Windows 8 App

Windows Phone 8 App

 Solution

  1. Launch Visual Studio 2012
  2. Goto "File" -> "New" -> "Project". The "New Project" dialog opens.
  3. Select "Templates" -> "Other Project Type" -> "Visual Studio Solutions" -> "Blank Solution
  4. Enter name of your solution as "Calculator"
  5. Click "OK"

 Calculator Library

  1. In Solution Explorer, Right-Click the solution. Goto "Add" -> "New Project". The "New Project" dialog opens.
  2. Goto "Visual C#" -> "Windows" -> "Portable Class Library"
  3. Enter name of project as "CalculatorLibrary". Click OK
  4. In the "Add Portable Class Library" dialog, ensure "Windows 7 and higher" and ".NET for Windows Store Apps" is selected. Click "OK"
  5. Rename "Class1.cs" as "Calculator.cs"
  6. Right click "CalculatorLibrary" project in Solution Explorer. Goto "Add" -> "New Item"
  7. Goto "Visual C#" - > "Code" -> "Class"
  8. Enter name of file as "Validation.cs"
  9. Replace contents of Calculator.cs with the following code
    Code Snippet
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5.  
    6. namespace CalculatorLibrary
    7. {
    8.     public class Calculator
    9.     {
    10.         private long? a;
    11.  
    12.         private long? b;
    13.  
    14.         private string calculatorOperator = null;
    15.  
    16.         private long display = 0;
    17.  
    18.         public Calculator()
    19.         {
    20.             Init();
    21.         }
    22.  
    23.         public void Init()
    24.         {
    25.             a = null;
    26.             calculatorOperator = null;
    27.             b = null;
    28.             display = 0;
    29.         }
    30.  
    31.         public string Display
    32.         {
    33.             get { return display.ToString(); }
    34.             set { display = long.Parse(value); }
    35.         }
    36.  
    37.         public void HandleInput(string s)
    38.         {
    39.             if (Validation.IsNumeric(s))
    40.             {
    41.                 if (calculatorOperator == null)
    42.                 {
    43.                     if (a == null)
    44.                         a = 0;
    45.                     a = a * 10 + Validation.ToNumeric(s);
    46.                     display = a.Value;
    47.                 }
    48.                 else
    49.                 {
    50.                     if (b == null)
    51.                         b = 0;
    52.                     b = b * 10 + Validation.ToNumeric(s);
    53.                     display = b.Value;
    54.                 }
    55.             }            
    56.             else if (Validation.IsOperator(s))
    57.             {
    58.                 if (b == null)
    59.                 {
    60.                     calculatorOperator = s;
    61.                 }
    62.                 else
    63.                 {
    64.                     Calculate();
    65.                     a = display;
    66.                     calculatorOperator = s;
    67.                     b = null;
    68.                 }
    69.             }
    70.             else if(Validation.IsEqual(s))
    71.             {
    72.                 Calculate();
    73.             }
    74.             else if (Validation.IsReset(s))
    75.             {
    76.                 Init();
    77.             }
    78.         }
    79.  
    80.         public void Calculate()
    81.         {
    82.             long result = 0;
    83.             switch (calculatorOperator)
    84.             {
    85.                 case "+":
    86.                     result = a.Value + b.Value;
    87.                     break;
    88.                 case "-":
    89.                     result = a.Value - b.Value;
    90.                     break;
    91.                 case "*":
    92.                     result = a.Value * b.Value;
    93.                     break;
    94.                 case "/":
    95.                     result = a.Value / b.Value;
    96.                     break;
    97.             }
    98.             display = result;
    99.         }
    100.     }
    101. }
  10. Replace contents of Validator.cs with the following code
    Code Snippet
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5.  
    6. namespace CalculatorLibrary
    7. {
    8.     public class Validation
    9.     {
    10.         public static bool IsNumeric(string s)
    11.         {
    12.             if (string.IsNullOrEmpty(s))
    13.                 return false;
    14.             if (s.Length > 1)
    15.                 return false;
    16.             char c = s.ToCharArray()[0];
    17.             return (c >= '0' && c <= '9');
    18.         }
    19.  
    20.         public static int ToNumeric(string s)
    21.         {
    22.             char c = s.ToCharArray()[0];
    23.             return (int)c - '0';
    24.         }
    25.  
    26.         public static bool IsOperator(string s)
    27.         {
    28.             if (string.IsNullOrEmpty(s))
    29.                 return false;
    30.             if (s.Length > 1)
    31.                 return false;
    32.             return (s.Equals("+") || s.Equals("-") || s.Equals("*") || s.Equals("/"));
    33.         }
    34.  
    35.         public static bool IsEqual(string s)
    36.         {
    37.             if (string.IsNullOrEmpty(s))
    38.                 return false;
    39.             return s.Equals("=");
    40.         }
    41.  
    42.         public static bool IsReset(string s)
    43.         {
    44.             if (string.IsNullOrEmpty(s))
    45.                 return false;
    46.             return s.Equals("C");
    47.         }
    48.     }
    49. }

Windows Phone 8 App

  1. In Solution Explorer, Right-Click the solution. Goto "Add" -> "New Project". The "New Project" dialog opens.
  2. Goto "Visual C#" -> "Windows Phone" -> "Windows Phone App".
  3. Enter name of Project as "CalculatorWindowsPhone". Click "OK"
  4. Ensure "Target Windows Phone OS version" is "Windows Phone OS 8.0". Click "OK"
  5. In Solution Explorer, in project "CalculatorWindowsPhone", Right-Click "References". Click "Add Reference"
  6. Goto "Solution" -> "Projects".
  7. Select "CalculatorLibrary". Click "OK"
  8. Open the file MainPage.xaml
  9. Within the Grid with Name "Content Panel", insert the following XAML code to define the User Interface
    Code Snippet
    1. < Grid.RowDefinitions >
    2.     < RowDefinition Height ="Auto"></ RowDefinition >
    3.     < RowDefinition Height ="Auto"></ RowDefinition >
    4.     < RowDefinition Height ="Auto"></ RowDefinition >
    5.     < RowDefinition Height ="Auto"></ RowDefinition >
    6.     < RowDefinition Height ="Auto"></ RowDefinition >
    7. </ Grid.RowDefinitions >
    8. < Grid.ColumnDefinitions >
    9.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    10.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    11.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    12.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    13.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    14. </ Grid.ColumnDefinitions >
    15. < TextBlock Grid.Row ="0" Grid.Column ="0" Text ="0" HorizontalAlignment ="Right" Grid.ColumnSpan ="5" VerticalAlignment ="Center" Name ="TextBlockDisplay"/>
    16. < Button Grid.Row ="1" Grid.Column ="3" Content ="C" Click ="Button_Click" Grid.ColumnSpan ="2"></ Button >
    17. < Button Grid.Row ="1" Grid.Column ="0" Content ="7" Click ="Button_Click"></ Button >
    18. < Button Grid.Row ="1" Grid.Column ="1" Content ="8" Click ="Button_Click"></ Button >
    19. < Button Grid.Row ="1" Grid.Column ="2" Content ="9" Click ="Button_Click"></ Button >
    20. < Button Grid.Row ="2" Grid.Column ="0" Content ="4" Click ="Button_Click"></ Button >
    21. < Button Grid.Row ="2" Grid.Column ="1" Content ="5" Click ="Button_Click"></ Button >
    22. < Button Grid.Row ="2" Grid.Column ="2" Content ="6" Click ="Button_Click"></ Button >
    23. < Button Grid.Row ="3" Grid.Column ="0" Content ="1" Click ="Button_Click"></ Button >
    24. < Button Grid.Row ="3" Grid.Column ="1" Content ="2" Click ="Button_Click"></ Button >
    25. < Button Grid.Row ="3" Grid.Column ="2" Content ="3" Click ="Button_Click"></ Button >
    26. < Button Grid.Row ="4" Grid.Column ="0" Content ="0" Grid.ColumnSpan ="2" Click ="Button_Click"></ Button >
    27. < Button Grid.Row ="2" Grid.Column ="3" Content ="/" Click ="Button_Click"></ Button >
    28. < Button Grid.Row ="2" Grid.Column ="4" Content ="*" Click ="Button_Click"></ Button >
    29. < Button Grid.Row ="3" Grid.Column ="3" Content ="+" Click ="Button_Click"></ Button >
    30. < Button Grid.Row ="3" Grid.Column ="4" Content ="-" Click ="Button_Click"></ Button >
    31. < Button Grid.Row ="4" Grid.Column ="3" Grid.ColumnSpan ="2" Content ="=" Click ="Button_Click"></ Button >
  10. Open MainPage.xaml.cs
  11. Inside class "MainPage" create private field of Calculator type
    Code Snippet
    1. Calculator calculator;
  12. Initialize this within Constructor
    Code Snippet
    1. calculator = new Calculator();
  13. Add the EventHandler for the Buttons to wire the User Interface with the calculator library
    Code Snippet
    1. private void Button_Click(object sender, RoutedEventArgs e)
    2. {
    3.     Button button = sender as Button;
    4.     calculator.HandleInput(button.Content.ToString());
    5.     TextBlockDisplay.Text = calculator.Display;
    6. }
  14. Run the Project to see the calculator in Action

Windows 8 App

The steps that we are going to do this in section is EXACTLY same as the steps we did in the previous sections.

 

  1. In Solution Explorer, Right-Click the solution. Goto "Add" -> "New Project". The "New Project" dialog opens.
  2. Goto "Visual C#" -> "Windows Store" -> "Blank App (XAML)".
  3. Enter name of Project as "CalculatorWindows". Click "OK"
  4. Ensure "Target Windows Phone OS version" is "Windows Phone OS 8.0". Click "OK"
  5. In Solution Explorer, in project "CalculatorWindows", Right-Click "References". Click "Add Reference"
  6. Goto "Solution" -> "Projects".
  7. Select "CalculatorLibrary". Click "OK"
  8. Open the file MainPage.xaml
  9. Within the Grid with Name "Content Panel", insert the following XAML code to define the User Interface
    Code Snippet
    1. < Grid.RowDefinitions >
    2.     < RowDefinition Height ="Auto"></ RowDefinition >
    3.     < RowDefinition Height ="Auto"></ RowDefinition >
    4.     < RowDefinition Height ="Auto"></ RowDefinition >
    5.     < RowDefinition Height ="Auto"></ RowDefinition >
    6.     < RowDefinition Height ="Auto"></ RowDefinition >
    7. </ Grid.RowDefinitions >
    8. < Grid.ColumnDefinitions >
    9.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    10.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    11.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    12.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    13.     < ColumnDefinition Width ="Auto"></ ColumnDefinition >
    14. </ Grid.ColumnDefinitions >
    15. < TextBlock Grid.Row ="0" Grid.Column ="0" Text ="0" HorizontalAlignment ="Right" Grid.ColumnSpan ="5" VerticalAlignment ="Center" Name ="TextBlockDisplay"/>
    16. < Button Grid.Row ="1" Grid.Column ="3" Content ="C" Click ="Button_Click" Grid.ColumnSpan ="2"></ Button >
    17. < Button Grid.Row ="1" Grid.Column ="0" Content ="7" Click ="Button_Click"></ Button >
    18. < Button Grid.Row ="1" Grid.Column ="1" Content ="8" Click ="Button_Click"></ Button >
    19. < Button Grid.Row ="1" Grid.Column ="2" Content ="9" Click ="Button_Click"></ Button >
    20. < Button Grid.Row ="2" Grid.Column ="0" Content ="4" Click ="Button_Click"></ Button >
    21. < Button Grid.Row ="2" Grid.Column ="1" Content ="5" Click ="Button_Click"></ Button >
    22. < Button Grid.Row ="2" Grid.Column ="2" Content ="6" Click ="Button_Click"></ Button >
    23. < Button Grid.Row ="3" Grid.Column ="0" Content ="1" Click ="Button_Click"></ Button >
    24. < Button Grid.Row ="3" Grid.Column ="1" Content ="2" Click ="Button_Click"></ Button >
    25. < Button Grid.Row ="3" Grid.Column ="2" Content ="3" Click ="Button_Click"></ Button >
    26. < Button Grid.Row ="4" Grid.Column ="0" Content ="0" Grid.ColumnSpan ="2" Click ="Button_Click"></ Button >
    27. < Button Grid.Row ="2" Grid.Column ="3" Content ="/" Click ="Button_Click"></ Button >
    28. < Button Grid.Row ="2" Grid.Column ="4" Content ="*" Click ="Button_Click"></ Button >
    29. < Button Grid.Row ="3" Grid.Column ="3" Content ="+" Click ="Button_Click"></ Button >
    30. < Button Grid.Row ="3" Grid.Column ="4" Content ="-" Click ="Button_Click"></ Button >
    31. < Button Grid.Row ="4" Grid.Column ="3" Grid.ColumnSpan ="2" Content ="=" Click ="Button_Click"></ Button >
  10. Open MainPage.xaml.cs
  11. Inside class "MainPage" create private field of Calculator type
    Code Snippet
    1. Calculator calculator;
  12. Initialize this within Constructor
    Code Snippet
    1. calculator = new Calculator();
  13. Add the EventHandler for the Buttons to wire the User Interface with the Calculator Library
    Code Snippet
    1. private void Button_Click(object sender, RoutedEventArgs e)
    2. {
    3.     Button button = sender as Button;
    4.     calculator.HandleInput(button.Content.ToString());
    5.     TextBlockDisplay.Text = calculator.Display;
    6. }
  14. Run the Project to see the calculator Windows 8 App in Action.

Conclusion

As you can see, using the Portable Class Library, we were able to pull out most of the code into a common library, which we then used as reference in the Windows 8 and Windows Phone 8 App. The only thing that we had to do in the Windows 8 and Windows Phone 8 App was defining the User Interface and wiring the User Interface with the common library. Note that the UI layer was exactly same for both platforms. With some effort, even this code can be pulled out in the common library.