Mobile Zone is brought to you in partnership with:

Michael Crump is a Microsoft MVP, INETA Community Champion, and an author of several .NET Framework eBooks. He speaks at a variety of conferences and has written dozens of articles on .NET development. He currently works at Telerik with a focus on our XAML control suite.
You can visit his blog at: MichaelCrump.Net or follow him on Twitter at: @mbcrump

Michael is a DZone MVB and is not an employee of DZone and has posted 111 posts at DZone. You can read more from them at their website. View Full User Profile

Using Portable Class Libraries with Windows 8 / Windows Phone 8 MVVM

01.17.2013
| 11713 views |
  • submit to reddit

Introduction

Portable Class Libraries (PCL) support the cross-platform development of .NET Framework applications. With Portable Class Libraries, you can write portable assemblies that share code with Windows 8, Windows Phone, Xbox 360 and other .NET applications. If you choose not to use them, then you must target a single application type and rework the class library for other application types as needed. PCLs save this work by allowing you to build assemblies that are shared across different platforms. In this article, we are going to use the MVVM (Model-View-View-Model) pattern with Portable Class Libraries that target Windows 8 apps and more! Let’s get started.

What’s required?

Before jumping in, we will need to make sure you have the required tools necessary to begin using Portable Class Libraries. Please look at the table listed below to see what action is required before beginning this tutorial.

Version of Visual Studio

Required Files to Download

VS2012

Nothing – Everything is already installed.

VS2010

Portable Library Tools

VS2008 and earlier

Not Supported.

We can quickly see from this table that VS2010 or newer is required to use PCLs. Earlier versions of Visual Studio are not supported as they don’t have support for later .NET Framework versions.

Getting Started

Once everything is installed or you are using Visual Studio 2012 (in which case, everything is already installed), then it is time to get started. In my example application, I will be using Visual Studio 2012, but the functionality remains the same even if you are using Visual Studio 2010 and have the Portable Library Tools installed.

Go ahead and select File-> New Project and under Templates select Visual C# then Portable Class Library as shown in Figure 1.

Figure 1: The New Project Dialog in Visual Studio 2012.

I’m going to name my project DZonePCL and hit the OK button. (I recommend that you do the same if you plan on copy/pasting the code snippets). The next dialog box that we see is “Add Portable Class Library” as shown in Figure #2.



Figure 2: The “Add Portable Class Library” Dialog.

From here, we can see that we have several target frameworks available to us:  the .NET Framework, Silverlight, Windows Phone, Window Store Apps and even Xbox 360. We are going to leave the default here and target everything except Xbox 360 and hit OK. The result of my choices is going to dictate the reference assemblies that are available to me that meet all of the requirements of those platforms.

Once our project launches, we have a it will simply contain an empty class library and a single reference to .NET Portable Subset.

Let’s go ahead and create a new class called DelegateCommand.  Paste the following code snippet into it, thus overwriting everything.

Note: If you did not name your project, DZonePCL then you will need to change the namespace to match the name of your project.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace DZonePCL
{
    public class DelegateCommand : ICommand
    {
        Func<object, bool> _canExecute;
        Action<object> _execute;

        public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            this._canExecute = canExecute;
            this._execute = execute;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
}

This is boilerplate code that can be found in many projects implementing MVVM.  Commands are a critical piece for projects that implement the MVVM pattern because they provide separation between a user interface and logic. Think of commands in MVVM as a way to avoid code-behind in your pages.

Now it is time to go ahead and create our ViewModel that will be used in the various applications. First, rename Class1.cs to CustomerViewModel.cs, then paste the following code, overwriting everything in the file:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace DZonePCL
{
    public class CustomerViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<string> _messages = new ObservableCollection<string>();

        public ObservableCollection<string> Messages
        {
            get { return _messages; }
            set { _messages = value; RaisePropertyChanged("Messages"); }
        }

        public CustomerViewModel()
        {
            SaveCustomerCommand = new DelegateCommand((obj) =>
                {
                    Messages.Add("Saved: " + obj.ToString());
                }, null);
        }

        public ICommand SaveCustomerCommand { get; set; }

        private void RaisePropertyChanged(string propertyName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;        
    }
}

From here you can see that we have a very simple implementation of a CustomerViewModel. This class implements the INotifyPropertyChanged interface and contains an ObservableCollection that maintains the list of Customers the user is saving. You should make a note that the CustomerViewModel constructor contains a SaveCustomerCommand that instantiates a new instance of our DelegateCommand adding the object entered into the ObservableCollection.

Creating our Windows 8 Application

Now that we have our Portable Class Library created, it is time to create our Windows Store Application that will use it. Begin by right-clicking on the solution, then clicking Add, then New Project. We are going to select Visual C# -> Windows Store -> Blank App (XAML) and give it the name of DZoneWin8XAML and hit OK.

Once our application loads up, we need to add a reference to our Portable Class Library. In Solution Explorer, Right-click on DZoneWin8XAML's References and choose "Add Reference". Then select Solution -> Projects and check the "DZonePCL" entry as shown in Figure 3.

Figure 3: Adding the Portable Class Library to our Windows 8 XAML/C# Application. 

To enable access to the newly-referenced DZonePCL project, open DZoneWin8XAML's MainPage.xaml and add the following namespace to the Page element's attributes:

xmlns:portable="using:DZonePCL"

Now we will need to set up the Page.Resources of our ViewModel, providing a key that we can use in XAML. Add the following inside the Page element contents, just before the Grid:

    <Page.Resources>
        <portable:CustomerViewModel x:Key="vm" />
    </Page.Resources>

Finally, we can setup our UI by replacing the Grid with the following code:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    	<Grid.ColumnDefinitions>
    		<ColumnDefinition Width="681*"/>
    		<ColumnDefinition Width="685*"/>
    	</Grid.ColumnDefinitions>
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
      
    		<TextBox x:Name="txtCustomerName" Margin="0,0,0,43"/>
    		<Button Content="Save Customer" Command="{Binding SaveCustomerCommand, Source={StaticResource vm}}"
    			CommandParameter="{Binding Text, ElementName=txtCustomerName}" />
    	</StackPanel>
            <ListView ItemsSource="{Binding Messages, Source={StaticResource vm}}" Grid.Column="1"/>
      
    </Grid>

In this example, we are going to allow the user to enter a Customer Name and click the “Save Customer” button. By using Commands, we can bind to the SaveCustomerCommand in our ViewModel (defined in our Portable Class Library) and execute it without any code behind. We also setup a CommandParameter to pass the Text in the txtCustomerName control. Finally, we use a new control in Windows 8 called the ListView and bind the ItemSource to the ObservableCollection called ‘Messages’ from our ViewModel. Our UI now looks like the following, as shown in Figure 4.

Figure 4: Our UI for the Windows 8 XAML Application using Portable Class Libraries.  ListView control is not visible as no items are added yet.

Let's see this simple UI in action.  First, set DZoneWin8XAML as the startup project by right-clicking on the project and choosing "Set as Startup Project".  Run the project and add several customers.  The app should now appear similar to Figure 5.



After you hit the “Save Customer” button, you will notice that your items animate into the ListView control. This is the beauty of using Windows 8. The animations are built into the control and we only have to be concerned with the logic. You should have noticed that we have no code in our code-behind page (MainPage.xaml.cs) and we have a true separation of concerns by using the MVVM pattern and Portable Class Libraries.

The Beauty of Portable Class Libraries

Time for code-reuse! If you remember at the beginning of this article, we selected .NET Framework, Silverlight, Windows Phone and Windows Store Apps. The View Model that we created in our Portable Class Library is ready to be re-used by any of those application types as if it was in our Windows Store App. If you have version 8.0 of the Windows Phone SDK installed, create a new Windows Phone 8 project, again making it the startup project, and add a reference to the same DZonePCL project.  Then we need only to make similar changes to MainPage.xaml that we did in the DZoneWin8XAML project.The only caveat to this is different form factors may require a new UI layout and some controls may not exist in other platforms (such as the ListView that we used in our Windows Store App). Below is the XAML used in a Windows Phone 8 project that uses our Portable Class Library with a brand new control in Windows Phone 8 called the LongListSelector.

<phone:PhoneApplicationPage
    x:Class="DZoneWP8.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:portable="clr-namespace:DZonePCL;assembly=DZonePCL"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.Resources>
        <portable:CustomerViewModel x:Name="vm"/>
    </phone:PhoneApplicationPage.Resources>

    <Grid x:Name="LayoutRoot" Background="Transparent">      
        
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="DZONE" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="pcl demo" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        	<Grid.RowDefinitions>
        		<RowDefinition Height="200*"/>
        		<RowDefinition Height="407*"/>
        	</Grid.RowDefinitions>
            <StackPanel Orientation="Vertical" VerticalAlignment="Center">
        		<TextBox x:Name="txtCustomerName" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False" d:LayoutRounding="Auto"/>
        		<Button Content="Save Customer" Command="{Binding SaveCustomerCommand, Source={StaticResource vm}}"
        			CommandParameter="{Binding Text, ElementName=txtCustomerName}" />
        	</StackPanel>
            <phone:LongListSelector ItemsSource="{Binding Messages, Source={StaticResource vm}}" Grid.Row="1"/>
        </Grid>
     </Grid>

</phone:PhoneApplicationPage>

After setting this project to our startup project and entering the same data, our application looks like Figure 6.

Figure 6: Our Windows Phone 8 project using Portable Class Libraries.

Again, you will see no code-behind and I simply rearranged the layout to fit our new form factor.

Conclusion

Hopefully by now you have seen the power of Portable Class Libraries with MVVM in your applications. We have walked through the steps of creating a Portable Class Library, targeting multiple frameworks and creating a ViewModel that can be shared throughout. We consumed the Portable Class Library in a Windows 8 and Windows Phone 8 application by using XAML’s powerful binding mechanisms. If you have any questions then feel free to leave them in the comments below. You may also follow me on Twitter at mbcrump or keep up with my blog by visiting michaelcrump.net.

DOWNLOAD CODE for this tutorial

AttachmentSize
DZonePCL.zip426.26 KB
Published at DZone with permission of Michael Crump, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)