Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Windows/Phone 8.1–Class Libraries, Portable Class Libraries, WinRT Components

Blogs

Mike Taulty's Blog

Elsewhere

Archives

Note: the official view of //Build comes, of course, from the keynote session at //Build and the individual speaker sessions so if you find that anything that I write here seems out of sync with what you see at //Build then, of course, you should apply a pinch of salt to what I’ve written – I can be wrong and it’s early days yet.

You should also check out these 2 blog posts:

Cortana (yes!) and Many, Many Other Great Features coming in Windows Phone 8.1

Extending platform commonality through universal Windows apps

I got a couple of comments in response to my previous post about “what kind of PCLs are these?” and “what’s a ‘Universal PCL’?” and so I thought I’d dig into that a little bit here as there are a number of ways of re-using .NET code in Windows/Phone 8.1 that weren’t all available to a Windows Phone 8.0 developer.

I’ll start with a blank, universal project which has the 2 separate Windows/Phone projects (or “heads” as you might hear Microsoft people calling them in //Build sessions) and a shared folder.

image

Adding a Portable Class Library

I think the key word with “portable class libraries” is the word “portable” and the question I always find myself asking is “portable across what?”. That is – I can make a portable class library to share across Windows/Phone 8.1 by doing this;

image

and that creates a .NET class libary (i.e. an assembly) which can be referenced by either/both of the Windows/Phone projects (usually, I think you’d be creating this library to reference from both). You can see this from the Properties page;

image

The important things about portable class libraries come from http://msdn.microsoft.com/en-us/library/gg597391(v=vs.110).aspx which tells me that the types for a PCL;

  • They must be shared across the targets you selected.

  • The must behave similarly across those targets.

  • They must not be candidates for deprecation.

  • They must make sense in a portable environment, especially when supporting members are not portable.

That portable class library that I make above is configured for Windows 8.1 and Windows Phone 8.1. I’m not sure of the best way to do this but if I look at the Object Browser in Visual Studio, it suggests that what I’ve got available to me here as a “surface area” of common APIs includes;

image

So that shows that I’ve got this “.NET Core” from .NET 4.5.1 framework and it also shows that I’ve got the common pieces of WinRT that Windows 8.1 contributes;

image

and I’ve also got the common pieces of WinRT that Windows Phone 8.1 contributes;

image

and if I take some representative class like XDocument (LINQ to XML) then I can use that from that portable class library;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        XDocument xDoc = XDocument.Parse("<foo/>");
      }
    }
}

equally, if I use some piece of WinRT that’s available to both Windows/Phone then I can do that too. For example;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        Button button = new Button();
        button.Content = "Hello Portable XAML World";
      }
    }
}

but what I can’t do is make use of some UI control that doesn’t exist to both Windows/Phone. For example;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This doesn't compile. Pivot doesn't exist on Windows 8.1.
        Pivot pivot = new Pivot();
      }
    }
}

or for an example the other way around;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This doesn't compile. SearchBox doesn't exist on Windows Phone 8.1
        SearchBox searchBox = new SearchBox();
      }
    }
}

or for a non-UI example I can use a shared API like;

namespace Portable
{
    public class Class1
    {
      public static async Task DoSomething()
      {
        StorageFolder photos = KnownFolders.PicturesLibrary;

        StorageFile file =
          await photos.CreateFileAsync(
            "myNewFile.txt", CreationCollisionOption.GenerateUniqueName);
      }
    }
}

but I can’t use a non-UI API that’s not available in both places;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This doesn't compile. ToastNotificationManager can't do History
        // on Windows 8.1
        ToastNotificationManager.History.Remove("burntToast");
      }
    }
}

and for one the other way around;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This doesn't compile. SearchPane doesn't exist on Windows Phone 8.1
        SearchPane searchPane = searchPane.GetForCurrentView();
      }
    }
}

Where can I use this “Universal Portable Class Library” from? I can really only use it from 2 places – a Windows 8.1 project and a Windows Phone 8.1 project or from another class library that’s targeting the same target platforms.

If I try to reference it from (e.g.) a Windows Console Application then I’m going to get an error;

image

what if I tried to reference this library from a Silverlight 8.1 project? Same error. But maybe I can change that, perhaps I can go and change the target platforms for my portable library;

image

and then, sure enough, I can reference this library now from Silverlight 8.1, Windows 8.1, Windows Phone 8.1 but what does this mean to the API set that I can call? As you’d expect, it reduces it because we’re intersecting an intersection or subsetting a subset or whatever you want to call it.

Can I now create a Button in my portable code? No, because a Silverlight 8.1 Button is not a Windows Phone 8.1 Button.

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This does not compile. Silverlight's Button is not Windows/Phone's
        // Button.
        Button b = new Button();
      }
    }
}

But can I still use XDocument? You bet;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        // This does not compile. Silverlight's Button is not Windows/Phone's
        // Button.
        XDocument xDoc = XDocument.Parse("<foo/>");
      }
    }
}

and can I still use async and Tasks etc? Yes;

namespace Portable
{
    public class Class1
    {
      public static async Task DoSomethingAsync()
      {
        await Task.Delay(1000);
      }
    }
}

and can I still use portable WinRT APIs that are available across Windows/Phone/Silverlight8.1 ? Yes;

namespace Portable
{
    public class Class1
    {
      public static void DoSomething()
      {
        var someTileXml = TileUpdateManager.GetTemplateContent(
          TileTemplateType.TileSquare150x150Block);
      }
    }
}

and so, when I’m creating a portable class library with that option in Visual Studio;

image

I don’t really think it’s doing anything different than creating a portable library for “Windows Desktop”;

image

and then pre-selecting these 2 target platforms for you;

image

As an aside, while I’ve got Xamarin.Android and Xamarin.iOS on the screen unless some magic happened at //Build that I didn’t see yet (it’s always possible!) if I add those 2 platforms here then I’m going to be subsetting down my available APIs such as to remove the possibility of invoking WinRT APIs as, of course, they aren’t portable across to Android/iOS. As I’ve said before if they were then things might be very interesting indeed Smile but they aren’t.

What About WinRT Components?

You can write WinRT components in .NET. A similar looking dialog can be used to do that portably. Like this;

image

I want to point out that this is not interchangeable with making a .NET class library. A WinRT component is a different beast. I’ll try and illustrate that like this;

namespace PortableWinRT
{
    public sealed class Class1
    {
      public static async Task<int> DoSomethingAsync()
      {
        await Task.Delay(5000);
        return (42);
      }
    }
}

This code doesn’t compile. Why? Because we’re making a WinRT component. A WinRT component’s type system is not the .NET type system which makes sense because a WinRT component can be used from a JavaScript, C++ or .NET application and so tying it to the .NET type system (or the JS or C++ type system) wouldn’t make sense. It has its own type system.

Consequently, I can’t use Task<int> as a return type. Now…there are fairly simple ways around this in this instance. I can so something like this;

namespace PortableWinRT
{
    public sealed class Class1
    {
      public static IAsyncOperation<int> DoSomethingAsync()
      {
        return (InternalDoSomethingAsync().AsAsyncOperation<int>());
      }
      static async Task<int> InternalDoSomethingAsync()
      {
        await Task.Delay(5000);
        return (42);
      }
    }
}

but the point is more that I wouldn’t just go and make a custom WinRT component unless I had a reason to do that. For me, that generally boils down to one of;

  1. You want to use the component in different language environments.
  2. You need to write a custom WinRT component because the system needs one – a prime example for me would be writing a background task implementation which (I think) has to be a custom WinRT component.

No doubt there are other reasons to make them but those are the primary two that come to mind for me at the time of writing the post and I’d take care with doing (1). 

I hope I got that right – feel free to let me know if I’ve goofed and I’ll fix.


Posted Fri, Apr 4 2014 11:55 AM by mtaulty

Comments

Krishna wrote re: Windows/Phone 8.1–Class Libraries, Portable Class Libraries, WinRT Components
on Fri, Apr 4 2014 12:17 PM

I've also noticed that with Xamarin iOS/Droid already installed, if you install VS 2013 Update 2 RC, some of the portable profiles in the reference assemblies folders () don't seem to be updated / supported. I can't use my portable lib that used to target W8, WP8, W81, .NET45, XamariniOS, XamarinDroid - with WP81.

I'm sure they APIs are present - since the subset of .NET APIs in WP8 and W8, W81 should be present on WP81 as well. Yes?

@knadiminti

Rehan Saeed wrote re: Windows/Phone 8.1–Class Libraries, Portable Class Libraries, WinRT Components
on Mon, Apr 7 2014 9:54 AM

"they aren’t portable across to Android/iOS. As I’ve said before if they were then things might be very interesting indeed Smile but they aren’t."

Microsoft, if you are listening and if you really are going to buy Xamarin. This is all us app developers ask for. I understand that Xamarin currently have their own abstraction layer but this would be amazing.

mtaulty wrote re: Windows/Phone 8.1–Class Libraries, Portable Class Libraries, WinRT Components
on Tue, Apr 8 2014 12:21 AM

Rehan,

Yes, that would be kind of amazing wouldn't it?

I have nothing that I can add - you know as much about it as I do and I've never heard that idea mentioned inside of the company other than by me :-)

I keep thinking about it though.

Mike.

Lior wrote re: Windows/Phone 8.1–Class Libraries, Portable Class Libraries, WinRT Components
on Wed, May 14 2014 7:27 AM

I guess i missed out some stuff since WP7, but what exactly is Silverlight 8.1 and how does it differ from "standard" WP8 ?