2

I want to create a PCL for .NET 4.5, Windows 8, Windows Phone 8.1 and Silverlight 5, however I am not able to use ICommand when checking all of these platforms, although all of them should support it according to MSDN.

Steps to reproduce:

  • Create a PCL project with .NET 4.5, Windows 8, and Silverlight 5
  • Create a class that implements ICommand and generate the members
  • Build succeeds

  • Add Windows Phone 8.1 in the project settings

  • Build fails (cannot find System.Windows)
  • If you remove either Silverlight or WP it works, but with both active at the same time it doesn't.

Is this is bug? Or am I missing something?

Daniel Sklenitzka
  • 2,116
  • 1
  • 17
  • 25
  • Have a look here ... http://stackoverflow.com/questions/20478138/portable-class-library-icommand-compilation-error-in-wpf-not-sure-how-to-reso – Mashton May 06 '14 at 10:11
  • I did, but it's a slightly different problem, and the solution doesn't apply here unfortunately. – Daniel Sklenitzka May 06 '14 at 11:28

3 Answers3

1

Unfortunately we weren’t able to support ICommand (and other ViewModel types such as ObservableCollection) in PCLs that target both Silverlight 5 and Windows Phone 8.1. I’d suggest dropping SL5 support from the PCL and supporting that platform via a non-portable library.

Daniel Plaisted
  • 16,674
  • 4
  • 44
  • 56
  • We would probably get a lot less questions about PCL if you spend a little time explaining exactly *why* you can't support it. SO is not a forum. – Hans Passant May 06 '14 at 18:20
  • @HansPassant The reason we weren't able to support it has to do with the technical details of how PCLs are implemented, which most devs shouldn't need to know or care about. The issue is that these types are in System.Windows.dll on Silverlight, but that DLL has the Windows Phone Silverlight UI stack on Windows Phone, which is blocked from loading in Windows Phone XAML apps (since they have a different UI stack). – Daniel Plaisted May 06 '14 at 18:59
  • @DanielPlaisted: I know this answer is a year old, but couldn't the OP take advantage of the "NuGet bait and switch" technique? In fact, a blog written in May 2014 specifically has you commenting on how to achieve this! http://dotnetbyexample.blogspot.com/2014/05/writing-behaviors-in-pcl-for-windows.html – myermian Jun 28 '15 at 20:11
0

I believe the best solution you can accomplish here is to create a shared project and put all of your code inside of it (VS2013.2+ required) and then created a PCL (profile 259) for everything but SL5 and then a SL5 class library (both with shared references to the shared project). This will give you the ability to target all platforms (but unfortunately require two empty assemblies for universal platform support).

@DanielPlaisted any input on whether or not MS will be refactoring very generic types (like ICommand) to less platform specific assemblies/namespaces? (sorry for asking but you seem to have inside knowledge).

pjs
  • 2,601
  • 1
  • 20
  • 24
  • I am putting some more thought into this because i don't really like this solution all that much. I am putting my work here: http://git.acrotech.io/acrotech.portableviewmodel.commands Basically the idea is to create a universally portable commanding library (Profile 344) that does not provide System.Windows.Input.ICommand support, but rather provides a mirrored compatibility copy of ICommand. Then additionally providing a sub-classed button control in a shared project (referenced to all WPF enabled platforms) that supports command bindings to the portable ICommand interface. Feedback welcome – pjs Jan 19 '15 at 18:27
0

While this question is a year old, I ran into a blog post that helps solve this problem: http://dotnetbyexample.blogspot.com/2014/05/writing-behaviors-in-pcl-for-windows.html -- This blog contains a download sample as well, so you can examine its inner workings. The blog works with the IBehavior interface, but the conept is the same.


Basically, the technique is called the "NuGet bait and switch"; you would need to create a NuGet package that contains a PCL library and a platform-specific library (one for each platform).

Let's imagine that your PCL is going to be called "AwesomeMvvm". You would need:

  • AwesomeMvvm (Portable Class Library)
  • AwesomeMvvm.Silverlight
  • AwesomeMvvm.Windows81
  • ...

When you attempt to use the ICommand interface in your portable class library (PCL), you will get an error stating Cannot resolve symbol ICommand. To solve this, simply create an interface making sure it is in the same namespace System.Windows.Input. Your portable class library can now compile!

Now that your portable class library is compiled, create your platform-specific libraries and add a reference to your portable class library to them. Each of these libraries only need one code file that contains the TypeForwardedToAttribute as an assembly-level attribute:

[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Windows.Input.ICommand))]

The final step is to create a single NuGet package containing the portable class library, as well as each platform-specific library. If you did everything correctly, add a reference from your NuGet feed and everything should work just fine. NuGet will prefer the platform-specific libraries whenever it can, each of which rely on the portable class library. The trick is that at runtime it will use the native version of ICommand because you specified to forward your portable class library version to be forwarded to the platform-specific version.

myermian
  • 31,823
  • 24
  • 123
  • 215