Using Portable Class Library in .NET 4.5 and Visual Studio 2012

Posted by: Mahesh Sabnis , on 11/12/2012, in Category .NET Framework
Views: 40853
Abstract: In this article, we will see what is a Portable Class Library (PCL) and its importance. PCLs are used to build portable assemblies which work across platforms like Windows 7, Windows 8, Windows Presentation Foundation (WPF), Silverlight, Windows Store Apps and Windows Phone apps

By now, I hope most of you have started exploring .NET 4.5 and VS2012. There are several new features in .NET 4.5 for the developer community. You can find these new features here.

In this article, we will see what is a Portable Class Library (PCL) and its importance. PCLs are used to build portable assemblies which work across platforms like Windows 7, Windows 8, Windows Presentation Foundation (WPF), Silverlight, Windows Store Apps and Windows Phone apps. This project supports subset of assemblies from .NET Framework, Silverlight, Windows Store apps and Silverlight. One of the advantage of this project is that a developer can write the application code once and without modification, this code can be shared across various client applications. This feature increases the re-usability of the application code.

 

The Portable Library Project, supports the following platforms:

  • .NET Framework

- .NET 4.0 and later. The default is .NET 4.5

- This includes Windows Presentation Foundation (WPF).

  • Silverlight

- Silverlight 4.0, this is the default selection.

- Silverlight 5.0.

  • Windows Phone

- Windows Phone 7.x, the default Selection.

- Windows Phone 8.

  • Windows Store Apps.
  • Xbox 360.

Using Portable Class Library Project Template in Visual Studio 2012

Consider the following architecture:

app_architecture

Now-a-days most of the Line-of-Business applications makes use of WPF, Silverlight, Windows Store Apps and even Windows Phone apps. It is a good practice to use patterns like Model-View-View-Model to keep systems loosely coupled. Also MVVM is the standard way for data binding in XAML based technologies like WPF, Silverlight, Windows Phone and Windows Store Apps. So if we have one common layer to maintain Commands, ViewModel and even the Service Adapter (for making call to external service), and make it available to all XAML based clients, then the development efforts can be reduced and the maintenance cost can also be controlled. The Portable Class Library does this for us. We can create it once and make it available to all clients and hence can have a central component for Commands, ViewModel etc.

Practical Implementation of the Portable Class Library

With the theory part out, let’s see how we can implement a Portable Class Library and use it in multiple frontend projects.

For the sample below, I have used SQL Server 2012 with Company Database and the table used is EmployeeInfo as below:

CREATE TABLE [dbo].[EmployeeInfo](
    [EmpNo] [int] IDENTITY(1,1) NOT NULL,
    [EmpName] [varchar](50) NOT NULL,
    [Salary] [decimal](18, 0) NOT NULL,
    [DeptName] [varchar](50) NOT NULL,
    [Designation] [varchar](50) NOT NULL,
CONSTRAINT [PK_EmployeeInfo] PRIMARY KEY CLUSTERED
(
    [EmpNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Task 1: Open Visual Studio 2012 and create a Blank solution

Task 2: In the solution, add a new WCF Service, name it as ‘WCF_DataService’. Set the target framework as .NET Framework 4.5. Rename IService1.cs to IService.cs and rename Service1.svc to Service.svc. Add a new ADO.NET Entity Data Model in the project, name it as ‘Company.Edmx’. Complete the Wizard by selecting Company Database and the EmployeeInfo Table. After completing the Wizard, the Entity Diagram will be as below:

edm

Task 3: Add the following method in the IService.cs:

[ServiceContract]
public interface IService
{
   [OperationContract]
   EmployeeInfo[] GetEmployees();
}

Implement the above method in the Service class as below:

[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
public class Service : IService
{
CompanyEntities objContext;
public Service()
{
    objContext = new CompanyEntities();
}
public EmployeeInfo[] GetEmployees()
{
    var Employees = objContext.EmployeeInfoes.ToArray();
    return Employees;
}
}

 

Build the project and test the service.

Task 4: In the solution, add the new Portable class library project :

portable_class_lib

After clicking the ‘OK’ button, pick the target platforms supported by the library

target_platform

Task 5: In this project, add the reference of the WCF Service created in the Task 2 to Task 3. In this library add a class file, name it as ‘CServiceAdapter.cs’. This will contain a class which makes an asynchronous call to WCF Service.

using System;

namespace CS_PortableClass_Library
{
    public interface IServiceAdapter
    {
        void GetEmployees(EventHandler<MyRef.GetEmployeesCompletedEventArgs> callback);
    }
   
    public class CServiceAdapter : IServiceAdapter
    {
        MyRef.ServiceClient Proxy;

       
        public CServiceAdapter()
        {
            Proxy = new MyRef.ServiceClient();
        }

        public void GetEmployees(EventHandler<MyRef.GetEmployeesCompletedEventArgs> callback)
        {
            Proxy.GetEmployeesCompleted += callback;
            Proxy.GetEmployeesAsync();
        }
    }
}

The above class defines proxy of the WCF service and makes an asynchronous call to it.

Task 6: In the class library, add a new class file, name it as ‘CommandRespository.cs’, this defines class which implements an ‘ICommand’ interface. This class defines constructor with ‘Action’ delegate as an input parameter. This means the command object declared using this class can execute a method without any input parameter. The implementation is as below:

using System;
using System.Windows.Input;

namespace CS_PortableClass_Library
{
    public class CommandRespository : ICommand
    {
        private Action _handler;

        public CommandRespository(Action handler)
        {
            _handler = handler;
        }
       
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

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

 

Task 7: In the class library project, add a new class file, name it as ‘CModelProvider.cs’. The class in this file implements an ‘INotifyPropertyChanged’. The class instantiate the ServiceAdapter class created in Task 5. This also exposes the command property using an object of CommandRepository class created in Task 6. The code is as below:

using CS_PortableClass_Library.MyRef;
using System.ComponentModel;

namespace CS_PortableClass_Library
{
    public class CModelProvider : INotifyPropertyChanged
    {

        public IServiceAdapter Adapter { get; set; }
        public CModelProvider() : this(new CServiceAdapter())
        {

        }
        public CModelProvider(IServiceAdapter adapter)
        {
            if (adapter != null)
            {
                Adapter = adapter;
                EmployeesCommand = new CommandRespository(GetEmployees);
            }
        }

        EmployeeInfo[] _Employees;

        public EmployeeInfo[] Employees
        {
            get { return _Employees; }
            set
            {
                _Employees = value;
                onPropertyChanged("Employees");
            }
        }

        public void GetEmployees()
        {
            Adapter.GetEmployees((s, args) => Employees = args.Result);
        }


        public CommandRespository EmployeesCommand { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged;

        void onPropertyChanged(string pName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(pName));
            }
        }
    }
}

The command property ‘EmployeesCommand’ will be bound with the XAML element and the Employees property will be bound with the Data-Bound element e.g. DataGrid or ListBox.

Task 8: Build the Library project and make sure that it is error free.

Creating Client Applications

Task 9: In the solution created in the Task 1, add a new WPF project, name it as ‘WPF_Client’. In this project, add a reference of the Portable Class Library.

Task 10: In the MainWindow.xaml, add the DataGrid and the Button element. Define the Class Library Namespace in the XAML and define an instance of the ‘CModelProvider’ class as below:

<Window x:Class="WPF_Client.MainWindow"
        xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:lib="clr-namespace:CS_PortableClass_Library;assembly=CS_PortableClass_Library"
        Title="MainWindow" Height="486.842" Width="805.263">
    <Window.Resources>
        <lib:CModelProvider x:Key="vm"></lib:CModelProvider>
    </Window.Resources>
    <Grid DataContext="{Binding  Source={StaticResource vm}}">
        <Button x:Name="btnLoadEmployees" Content="Load Employees"
                HorizontalAlignment="Left" Margin="41,45,0,0" VerticalAlignment="Top"
                Width="697" Height="66"
                 Command="{Binding EmployeesCommand}"/>
        <DataGrid x:Name="dgEmployees" HorizontalAlignment="Left"
                  Margin="41,138,0,0" VerticalAlignment="Top" Height="277" Width="697"
                   ItemsSource="{Binding Path=Employees}"/>
    </Grid>
</Window>

If you carefully see the code, the Portable Assembly is registered in the Windows Tag with tag prefix as ‘lib’. The instance of the CModelProvider Class is defined using the key as ‘vm‘. The ‘EmployeesCommand’ is bound with ‘Button’ element. The Employees property is bound with the DataGrid.

Task 11: Run the WCF Service. After the WCF Service starts, run the WPF application. Click on the ‘Load Employees’ button. The result will be as shown below:

wpf_res

 

Task 12: Add the Silverlight Application in the same solution. Add a reference to the Portable Class library. In the MainPage.xaml, add the DataGrid and the button and set the DataBinding expression to the EmployeeCommand and the Employees property as shown below:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    x:Class="Silverlight_Client.MainPage"
    xmlns:lib="clr-namespace:CS_PortableClass_Library;assembly=CS_PortableClass_Library"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <lib:CModelProvider x:Key="vm"></lib:CModelProvider>
    </UserControl.Resources>
        <Grid x:Name="LayoutRoot"
              Background="White" Margin="0,0,-320,-164"
              DataContext="{Binding  Source={StaticResource vm}}">
        <Button x:Name="btngetemployees" Content="Button" HorizontalAlignment="Left"
                Margin="26,35,0,0" VerticalAlignment="Top"
                Width="684" Height="52"
                Command="{Binding EmployeesCommand}"/>
        <sdk:DataGrid x:Name="dgemployees" HorizontalAlignment="Left"
                      Height="297" Margin="26,133,0,0" VerticalAlignment="Top"
                      Width="684"
                      ItemsSource="{Binding Path=Employees}"/>
</Grid></UserControl>

Run the Silverlight application and the result will be as below:

silv_res

Task 13: In the same solution, add a new Windows Store Application, name it as ‘Windows_Store_Client’. In this project, add the reference of the Portable Class Library. Add the following XAML in the MainPage.Xaml. Register the Portable class library in the ‘Page’ . Add the Button element and the ListBox in the XAML. The code is as below:

<Page
    x:Class="Windows_Store_Client.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows_Store_Client"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:lib="using:CS_PortableClass_Library"
    mc:Ignorable="d">
    <Page.Resources>
        <lib:CModelProvider x:Key="vm"></lib:CModelProvider>
        <DataTemplate x:Key="emptemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding EmpNo}"></TextBlock>
                <TextBlock Text="{Binding EmpName}"></TextBlock>
                <TextBlock Text="{Binding Salary}"></TextBlock>
                <TextBlock Text="{Binding DeptName}"></TextBlock>
                <TextBlock Text="{Binding Designation}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
          DataContext="{Binding Source={StaticResource vm}}">
        <Button x:Name="btnloadEmployees" Content="Load Employees"
                HorizontalAlignment="Left" Margin="96,64,0,0"
                VerticalAlignment="Top" Height="92" Width="1137"
                FontSize="22"
               Command="{Binding Path=EmployeesCommand}"/>
        <ListBox x:Name="lstemps" HorizontalAlignment="Left"
                 Height="393" Margin="96,233,0,0"
                 VerticalAlignment="Top" Width="1137"
                 ItemsSource="{Binding Path=Employees}"
                  ItemTemplate="{StaticResource emptemplate}"/>

    </Grid>
</Page>

Task 14: Run the Windows Store App. The result is as shown below:

 

win_store_apps

Conclusion

Using Portable Class Library, it is possible to create an application layer which can be shared across various clients. Typically this project template is more useful for MVVM pattern application.

Download the source code (GitHub)

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Mahesh is having 10 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by watan on Thursday, June 20, 2013 12:03 PM
how can write code for student library for login form using username and password for each student in database
Comment posted by Edax Ucles on Monday, August 5, 2013 12:03 AM
Excelente Article! i founded very usefull! thanks!!!

Best Regards from Honduras!
Comment posted by Xavier on Sunday, September 29, 2013 2:20 PM
Hi Mahesh, Thanks for this article. Just two questions:
How can we adapt your solution to use params and also to add update/insert/delete methods exposed via WCF ?
Comment posted by Er Mukesh Kumar on Tuesday, March 4, 2014 4:35 AM
Awesome Explanation! Cheers..
Comment posted by Madhu on Saturday, March 8, 2014 1:08 PM
Do u have any idea "how can we can call the PCL methods from jquery.?

Please suggest me..

Thanks in advance
Comment posted by Ivan Ordoñez on Monday, March 17, 2014 3:26 PM
Hi!, I Can't Find How To Manage Common Storage Libraries for SL and WPF, Can't Anyone help me? Please!

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel