#GIS from a .NET developer's perspective

Disclaimer: This article is written based on Windows 10 Tech Preview – Build 10041. Things might change completely in the future.

On Windows Phone Silverlight 8.0 it was possible to continue run an while the app wasn’t foregrounded. This was useful for Turn-by-turn or run-tracker type of apps. So even if you got a phone call or turned the screen off, the app would continue to run. Unfortunately that functionality was removed (well not removed, but rejected in certification) from Windows Phone Silverlight 8.1, and it was never added to Windows Runtime apps. That meant you were pretty much stuck on Silverlight 8.0 if you were building any of these apps.

However, in Windows 10 the functionality is finally here with the Windows Runtime! There’s not a lot of doc on it, and especially on phone it seems rather buggy, but I’ll try and explain the gist of it here.

First let’s create a new app, and add some basic location tracking to it.

When you run this app, you’ll start seeing coordinates getting added to the list about once every second.

Now if you were to minimize the app (if you run as a desktop app – not a phone app), and return to the app, you might notice that the app still got coordinates added while it was minimized. That’s probably because you had the debugger attached. Try running the app without Visual Studio debugging, and you’ll notice the app will completely pause when it’s minimized. That means the app will stop tracking you if it’s not active. So first lesson: The Visual Studio debugger lies to you and prevents the app from suspending.

If we want to continue running the app while another app is active (or on a phone get an unexpected phone call), we now have a new “Extended Execution” session that we can start.

private ExtendedExecutionSession session;

private async void StartLocationExtensionSession()

{

session = new ExtendedExecutionSession();

session.Description = "Location Tracker";

session.Reason = ExtendedExecutionReason.LocationTracking;

session.Revoked += ExtendedExecutionSession_Revoked;

var result = await session.RequestExtensionAsync();

if (result == ExtendedExecutionResult.Denied)

{

//TODO: handle denied

}

}

This tells the app that we’d like to continue even if the app is backgrounded. So you would usually call this API when you start running or doing your route.

Similarly we can stop the execution by disposing the session:

if (session != null)

{

session.Dispose();

session = null;

}

You would typically call this at the end of the run or when you reach your destination.

The only piece we’re missing is the Revoked event – I’m not entirely sure when this fires (there’s no documentation available yet), but on the Windows Phone emulator it fires the moment you leave the app, so I haven’t been able to get this working there.

Now add this to your app and call the StartLocationExtensionSession method and minimize your app. Wait a little and come back to it – note that points have been collected while the app wasn’t active. So now you can go write your run tracker app for Windows Desktop and take your desktop computer for a run… or wait for a Windows Phone 10 build where it’s working

Disclaimer: This article is written based on Windows 10 Tech Preview – Build 10041. Things might change completely in the future.

The Windows 10 Preview SDK was finally released, and we all finally get a peek at what the new Universal App Projects (UAP) are all about. It’s one binary that will run everywhere. This means that it’s also one XAML to run both on Windows and Windows Phone. But because the user experience is usually quite different you might want a different UI for it. So a new functionality was added to Visual State that allows you to easily change the layout based on the width of your window. So the idea is that the layout adapts not based on device, but by screen real-estate. Here’s what that could look like:

<Grid>

<VisualStateManager.VisualStateGroups>

<VisualStateGroup>

<VisualStatex:Name="narrow">

<VisualState.StateTriggers>

<AdaptiveTriggerMinWindowWidth="0"/>

</VisualState.StateTriggers>

<VisualState.Setters>

<SetterTarget="status.Text"Value="Narrow view"/>

</VisualState.Setters>

</VisualState>

<VisualStatex:Name="wide">

<VisualState.StateTriggers>

<AdaptiveTriggerMinWindowWidth="600"/>

</VisualState.StateTriggers>

<VisualState.Setters>

<SetterTarget="status.Text"Value="Wide view"/>

</VisualState.Setters>

</VisualState>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

<TextBlockx:Name="status"FontSize="40"

HorizontalAlignment="Center"VerticalAlignment="Center"/>

</Grid>

So the basic idea is that by using the AdaptiveTrigger, when the window gets small enough, switch to the phone/narrow UI. So on a phone it’ll probably always be this UI used. Pretty neat, and allows for a similar experience across devices, but adapt for bigger screens.

When taking a closer look at the StateTriggers property, it takes a collection of ‘StateTrigger’, which is an abstract class that AdaptiveTrigger inherits from. So it stands to reason that perhaps we can create our own state triggers?

Supposed basing your UI on the width isn’t good enough, and you want to base it on the platform you’re on (Windows vs Windows Phone), we can create a new state trigger for this purpose. All we have to do is call the base method SetTriggerValue(bool) whether the conditions of the state is enabled or not. So here’s what a class like that would look like:

IsTypePresentStateTrigger: Enabled/disable UI based on whether a certain API is available. For instance if a hardware back button is present (usually Windows Phone), we can hide the back button from the UI, and free up some screen space.

Now the next question is: Does these values support binding? If they do, these triggers could be the new equivalent of WPF’s DataTriggers. So let’s create a simple data trigger that turns something on, based on a boolean. We can implement a simple IsTrueStateTrigger / IsFalseStateTrigger and just call the base method if the value we bound is true or not.

<VisualState>

<VisualState.StateTriggers>

<triggers:IsTrueStateTriggerValue="{Binding MyBoolean}"/>

</VisualState.StateTriggers>

<VisualState.Setters>

<SetterTarget="box.Visibility"Value="Collapsed"/>

</VisualState.Setters>

</VisualState>

Of course I could use a value converter for this as well, but this has a lot greater flexibility – a converter would have to be written to convert to Visible/Collapsed state, whereas this trigger can set any property to any value type.

Got any more ideas for useful generic state triggers? Fork and make a pull request!

In my second blog post, I wrote a little console app that acts as a small webserver that allows Windows Store and Windows Phone apps to register themselves as a push target, and the console app can send push messages to these apps. In this blog post we’ll use Jer’s mono hack to get this running on the Galileo.

First, we need to “install” mono on Galileo. Jump to Jer’s blog post and grab the mono_iot.zip file at the bottom of his blog post. Next unzip this file to the Galileo in a root folder like \mono\. You can access the Galileo in a network path by adding \c$\ to the network path. Ie. unzip into: \\mygalileo\c$\mono\ (if your device name is ‘mygalileo’ or replace it with the name or IP number). If you haven’t done this before, you’ll be prompted for username/password. Enter “mygalileo\Administrator” and your admin password. That’s really all that’s required for ‘installing’ mono.

Now to run a .NET app, all you have to do is call [path-to-mono.exe] [path-to-my-app.exe] to launch the app with the mono runtime. Almost any .NET console app will work. Ie:

c:\mono\bin\mono.exe c:\sampleapp\ConsoleApp1.exe

Next, we’ll run the push service app from my previous blog post. Compile the PushService app (yes you can use Visual Studio – no need for the Mono compiler) and copy it to the Galileo. Then open a Telnet terminal to Galileo, and start the service:

c:\mono\bin\mono.exe c:\PushService\PushService.exe

Next, update the client store/phone app to point to the IP of your galileo device, and make sure it’s on the same network. When running the app, you should now be able to register with the push service.

CTRL-Q to quit doesn’t seem to work. I’m guessing the CTRL key isn’t sent via telnet. You can just hit CTRL-C to quit the app.

Also if you press “S” to push a message, you’ll notice that the app fails. This is because the push notification hits an SSL secured server, and Mono doesn’t come with any SSL roots certificates installed. An in-depth article is describing this here: http://www.mono-project.com/docs/faq/security/ and here: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/ . Note though that the current Mono build you installed doesn’t seem to work for the certificate imports, so most of the solutions might not work for you. As a TEMPORARY alternative, we can get rid of the SSL certificate validation. Note: This is quite dangerous and should NOT be used in production. But for testing this is fine (if you think this is not a big deal, think again – iOS and MacOS had this issue recently and it was a MAJOR security problem). To disable validation, we basically just take over validation and return ‘true’ to say the certificate is fine regardless of it’s contents. You could also enhance this yourself by performing your own validation. To do this, all we need to add is the following line of code when the console app starts up:

Now redeploy the app, and you can now get your Galileo to perform push messages straight to your phone or tablet! How cool is that???

This is all the starting pieces you need to build a small simple .NET based webserver for controlling your Galileo. At the same time it’s all you need for getting your Galileo to notify you of certain events occurring. Bottom line: It’s the first big step into a .NET based home automation controller. The next big step is to create the building blocks for a trigger –> event system, so we can start automating and monitoring our home with the power of .NET and Windows on Devices.

In my intro post for my home automation project, I described a part of the app that sends temperature, humidity and power consumption measurements and pushes them to my phone. In this blogpost, we’ll build a simple console-webservice that allows a phone to register itself with the service, and the service can push a message to any registered device using the Windows Notification Service. Even if you’re not building a home automation server, but just need to figure out how to push a message to your phone or tablet, this blogpost is still for you (but you can ignore some of the console webservice bits).

To send a push message via WNS to an app, you need the “phone number of the app”. This is a combination of the app and the device ID. If you know this, and you’re the owner for the app, you are able to push messages to the app on the device. It’s only the app on the device that knows this phone number. If the app wants someone to push a message to the device, it will need go share it with that someone. But for this to work, you will first have to register the app on the Microsoft developer portal and associate your project with the app in order to be able to create a valid “phone number”.

Here’s the website after registering my app “Push_Test_App”. You simply create a new app, and only need to complete step 1 to start using WNS.

Next you will need to associate your app with the app you created in the store from the following menu item:

Simply follow the step-by-step guide. Note that the option is only available for the active startup-up project. Repeat this for both the store and phone app if you’re creating a universal project (make sure to change the startup project to get the menu item to relate to the correct project).

This is all we need to do to get the app’s “phone number” the “channel uri”. We can get that using the following line of code:

Notice that the channel.Uri property is just a URL. This is the URL to the WNS service where we can post stuff to. The WNS service will then forward the message you send to your app on the specific device.

Next step is to create a push service. We’ll create two operations: A webservice that an app can send the channel Uri to, and later an operation to push messages to all registered clients.

Note: You will need to launch this console app as admin to be able to open the http port.

Next, let’s add some code to our phone/store app that calls the endpoint and sends its channel uri and device id (we won’t really need the device id, but it’s a nice way to identify the clients we have to push to and avoid duplicates). We’ll also add a bit of code to handle receiving a push notification if the server was to send a message back (we’ll get to the latter later):

Now if we run this app, we can register the device with you service. When you run both, you should see a “client registered” output in the console. If not, check your IP and firewall settings.

Lastly, we need to perform a push notification. The basics of it is to simply post some content to the url. However the service will need to authenticate itself using OAuth. To authenticate, we need to go back to the dev portal and go to the app we created. Click the “Services” option:

Next, go to the subtle link on the following page (this link isn’t very obvious, even though it’s the most important thing on this page):

The next page has what you need. Copy the highlighted Package SID + Client Secret on this page. You will need this to authenticate with the WNS service.

The following helper class creates an OAuth token using the above secret and client id, as well as provides a method for pushing a message to a channel uri using that token:

Now run the console app and the phone/store app. First click the “register” button in your app, then in the console app click “S” to send a message. Almost instantly you should see the server time printed inside your app.

Note: We’re not using a background task, so this will only work while the app is running. In the next blogpost we’ll look at how to set this up, as well as how to create a live tile with a graph on it.

You can download all the source code here: Download (Remember to update the Packet SID/Client Secret and associate the app with your own store app).

For those who have been following me on twitter, you might have noticed I’ve been playing a lot with home automation lately. I’m planning on blogging about my experiences, and how some of the pieces are put together. At this point it’s far from a full solution – just a lot of pieces and custom ugly code wired together to get some things going. In the long term, I hope to have a fully configurable and extensible home automation system, but that would probably take me a few years to get there. This is the first in a series of blogs about my experiences, and why I’m doing it the way I am. I would love to hear your inputs and ideas in the comments.

In this first post I’m going to talk about what hardware my system consists off.

Devices, protocols etc.

There’s a lot of “internet of things” devices out there already today. Unfortunately there’s also a lot of standards. And a lot of competition to get the standards to succeed. It’s like the VHS vs Betamax wars right now. Any or all might win. And some systems supports multiple. Of some of the main ones on the market today:

Insteon / X10

Z-Wave

Zigbee

These standards allow devices to talk together using a common protocol, but they usually need a hub or bridge to configure it all. Several companies have then built controller hubs or bridges on top of these standards. This is where I think the entire system starts breaking down: Each company doesn’t want to help the other company, and that means each company has their own standards for talking to the controller, their website or no API at all. Another thing I’ve noticed: Most of these systems only work if you’re connected to the internet (if so the controller is usually called a “gateway”). If your internet is down you suddenly can’t control your house, your sprinklers might not run, AC is inoperable etc. And you also put a lot of trust in to that company’s security. The Heartbleed drama is a good example of why I find this really concerning. Especially considering that from their website you can see if anyone is home, disable the alarm and cameras and unlock the door, then put it all back in place as if nothing happened when they are done robbing your house. Add to that, that many controllers only works connected if you also purchase a subscription.

Lastly because all the controllers that do offer APIs, are all different. That means if I were to build a Home Automation App, I would have to either choose one of the controllers and have vendor-lock-in, meaning I would severely reduce the number of people who could use my app. Or I would have to buy all the controllers out there and build an abstraction layer. Neither of this I found very appealing either – especially considering the winning standards is still unknown.

So instead I started something else: I created my own controller software, and started to put some abstraction in into it, and uses MEF to allow extending it with more controllers – allowing others to contribute with plugins. The controller service software runs on my home PC, and is running completely offline. It’s really an “Intranet of Things”. When my phone is on the home wifi, it can talk directly to the server, and register for push updates, and the server software can push notifications to my phone, even when I’m not on the wifi. This allows me to do one-way monitoring of my phone. And if I need direct access, I can always VPN home. Lastly by not relying on a server online, I don’t have to pay, manage, scale, deal-with, build, setup etc any cloud services. It’s all self-contained – however it doesn’t prevent me from pushing data out on the internet, or connecting to a cloud service if I really wanted to.

I recently got a Galileo device, and ultimately I want to make this service run on this:

This is just a command-line version of Windows running on a really cheap piece of hardware. That means anyone could use my server software very cheap, or just install it on a PC. Well… that’s the long term plan anyway. The WindowsOnDevices version is still in its early stages and doesn’t have everything I need yet. So for now, it runs on my PC.

The hardware I’m using

I settled on the Zigbee standard for myself (for now). I like some of the promises of Zigbee as well as some of the supported devices out there. Some of the reasons I went with Zigbee:

Zigbee is an extremely low-power mesh network. The mesh network means the more devices you have, the better/stronger network you have. Some devices can run 10 years on a tiny battery.

A lot of utility companies have chosen this standard to allow you to read your power consumption real-time as well as current KwH cost, total consumption etc.

More and more companies seems to be adding support for it, meaning device prices are slowly coming down.

The USB controller I got works directly with the Zigbee network giving me full very fine-grained control (but see cons further down)

There are some cons with Zigbee too though.

License cost for Zigbee means the devices can be a little pricy.

There’s several sub-standards. Zigbee HA is for home automation. Zigbee SE is a more secure version used for your smart meters. You’ll need two separate controllers to monitor both (at least they are very similar to talk to though).

The standard is very flexible, which means it’s also pretty complex. Some controllers abstracts this away though (not mine).

In addition there’s a new “light link” standard for HA that the Philips Hue lights run on – I believe this allow it to run controller-less. Unfortunately my HA controller doesn’t support Light Link, and the manufacturer still hasn’t updated the firmware (which btw I can’t even update myself).

The USB Controller (or ‘coordinator’ in ZigBee speak) I have is using a VERY low-level API. It’s a lot of bit-wise operators and working with raw binary data coming in and out. It was a LOT of work just getting it working somewhat. And if you choose a different controller, most or none of my zigbee code is re-useable.

The door sensor only uses power when it opens or closes – it’s estimated battery life is 10 years. The Temp/Humidity sensor reports measurements every 3 mins (configurable), and should last about 3 years. I have a a couple of these, plus more door sensors on the way, as well as a Philips Hue light bulb.

At this point, I wrote a little piece of software of my PC that monitors messages coming in on the ZigBee network, and turns them into push notifications. It creates a nice live-tile graph of temperature , humidity (inside and out) and recent power consumption (I’ll blog about this in a later article).

It even allows me to configure alerts when a value exceeds a certain level:

This is actually very useful when I brew beer. Since I don’t have a temperature-controlled brew-keg, this is the second best. I put the sensor in with the keg, and I get alerts on my phone when the wort is too hot or cold.

I addition I can also monitor my power consumption using a separate (but similar) Zigbee SE receiver. It sends the same graph to my phone, but my local app monitors changes in usage down to the second (I push the usage graph a lot rarer to save phone battery). It’s interesting to see what uses power and not, and how much drain it causes. You can actually see a light turn on, or when the fridge thermostat turns on and off. It’s very educational about your power consumption, and how much standby power you use. You can also read what the current cost of electricity is to help you make certain decisions.

I also recorded a video of this here: 1liLQbq. You can see the graph jump 1-2 seconds after I turn a light on or off.

More devices…

California is in a severe drought right now. That means there’s a lot of water restrictions in effect, including what days you can water, and what types of watering you’re allowed to do. The sprinkler time I had couldn’t automatically do this, so I just bought a new one. OpenSprinkler which is an open-source Arduino based controller. It can connect to the local network and be remotely controlled. It even has a little REST API (albeit fairly undocumented but source code is available for reverse engineering).

While the software and web interface is pretty simple, it actually works very well. It even has a Windows Phone and Windows store app (based on Cordova). I’ve also started a little project to build a .NET API for this controller so I can integrate it into my “system”. Source-code for that is all available on Github: https://github.com/dotMorten/OpenSprinklerNet

I also have a couple of ZigBee-supported AC thermostats on the way, as well as some better and prettier window sensors that I would actually considering putting up (it’s beyond me why anyone would make such an ugly sensor to mount on all windows).

What’s next

I want to build an “If this then that” style configuration for my server software. Currently all I can do is push measurements out. Next is to set up rules and make things happen with the rules are satisfied. For example “If air condition is running and a window is open, send alert”. Or “If phone/me leaves the house and a window is open, alert” Or “if it was hot, windy and dry yesterday, increase lawn watering”. Or “If outside temperature and humidity is at a certain level and inside humidity doesn’t exceed a certain level, switch from air condition to swamp cooler”. The last example is actually what got me started: I have two air condition units (upstairs and downstairs), 5 whole-house fans, and two swamp-coolers. What’s more efficient to run (or combination thereof), is quite tricky and also depends on outside and inside conditions. I live in a very old house with really poor insulation, so choosing the cheapest cooling system during the very hot summers here could save me a lot of money. A fancy rule-based system for making those decisions is what I really need. Add to that, I could tweak that decision making using weather forecasts, my current location (or my phone’s that is), and the current electricity cost.

And I want to make it pluggable. It shouldn’t just be Zigbee, or just the devices I have. I want to make it so that you can quickly add more devices and protocols by adding a plugin. It’s definitely quite a software engineering task – if you have some experience with this, I’d love to hear your design ideas. I’ll put it all on Github for people to use – and hopefully to contribute.

Then next, would be getting it all to run on the Galileo board, but there’s still some .NET and USB support lacking so for now it’ll run on a PC.

It’s a big task – it’ll take some work and time. So in the mean time I’ll be blogging about how some of the pieces are built. Stay tuned…

I usually have a zero-tolerance when it comes to build warnings. While granted often the warnings are benign, having a lot will very often hide the important ones. Sometimes I even set the option “treat warnings as errors” to help me enforce this. When you’re building a library, you should also add XML doc comments to your classes and members, so you get full intellisense support in the projects you’re using it from. Just remember to check off the following check box:

This also have the benefit of giving you warnings for missing doc comments on public members, so you remember to write proper doc. However if you’re building for Windows Store or Phone, there’s a good chance you’ll see these four warnings now:

These are coming from code auto-generated by the compiler which exposes a set of public classes. You can even see these in intellisense:

This is a major issue in my mind. First of all it introduces warnings in code you didn’t write, and it pollutes your class library with methods that are not meant to be used. Here’s what this auto-generated class looks like:

The fix seems simple: Just go in and add the doc comments, and problem is solved, right? Not really. The problem is any changes you make to this file is overwritten every time you build. So we need to tweak the file right after it’s being generated, but right before it’s being compiled, but who’s that fast?

Enter: The Build Task

We can use a build task to do exactly that, and tell Visual Studio to let us know that its about to compile the code and fix it ourselves.

First create a new empty Windows Class Library, and add the following two references:

Next add the following class and compile:

XamlTypeInfoBuildTask.cs

using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System;

What does this class do? Simple: It has one property: The folder where the intermediate files including XamlTypeInfo.g.cs is. It then opens the file to be modified, and first injects “#pragma warning disable 1591” at the header which disables doc warnings, and re-enables it again at the bottom. At the same time we hide the class from intellisense, by setting the EditorBrowsable attribute on the class. This doesn’t really remove the class from the assembly – it just tells Visual Studio to skip showing this for intellisense.

To use this build-task, we need to add a little bit to the project file that causes this issue. We’ll first create a .targets file with the parameters for buildtask. Place this next to the compiled DLL (and use the name of the dll where highlighted):

This tells the project to run this before the compilation after the markup has been processed. It also sets the IntermediateOutputPath property on our build task, so the build task can find the file.

Now the last step is to reference this .targets file from the csproj file. Open the csproj file up in notepad, and scroll down to the <Import…/> tags, and add the following (remember to modify the highlighted paths to where the targets file is:

Making all this simpler

Naturally this is a bit of a pain having to set up over and over again. So unless you ever have to do a similar build task, you can forget everything you just read (sorry ), and just use the Nuget package I created that’ll do all this for you.

Simply add a reference to this nuget package, and the build task dll is downloaded and the .targets file auto-referenced.

We just released the second beta drop of the 'ArcGIS Runtime for .NET SDK', which now supports both Windows Store 8.1, Windows Phone 8.1 in addition to WPF. This means you can now build universal apps with a map control that supports all these platforms. We also released the package on NuGet for your convenience.

As a demonstration how quick it is to create a Windows Phone and Windows Store app, here's a little video creating a universal map app from scratch in 80 seconds:

Note: The nuget package currently doesn't support WPF. You will need to download the full setup to get WPF support as well, instead of using the nuget version.

At Build 2014, Microsoft announced the new ‘Universal Apps’ project type that allows you to share code between Windows Phone and Windows Store apps, using a new ‘shared’ project. Below is an example of the default hub project that shares a lot of the code has individual views for the parts where you want to tweak the UI specifically for phone or tablets.

Before we had shared projects, we could do something similar, by linking the same code files into multiple projects. It worked fairly well, but which ever project you open the file from, is the ‘context’ you look at it, so intellisense etc might not match the platform you’re looking at. The universal apps really aren’t any different. This is really just a nice tooling on top of linked files that makes it easier to work with. Also it is much easier to change the ‘context’ the code is viewed in using a simple dropdown above your code:

As shown above, you can still use compiler conditionals to write individual differences for each platform and still share the rest of the code file. So again this is the same as when working with linked files, but the shared project makes this much easier.

So how does this really work? If we look in the project file for Windows Phone or Windows Store project you’ll find the highlighted tag:

So the specific project simply references another project – kind of like how a linked file works, but in this case an entire group of files. Looking in the shared project that’s references, you find a fairly simple file, but this in turn references a file called [ProjectName].Shared.projitems, and the contents of this is really just a standard project with the files etc that needs to be referenced in the referencing project.

The last piece to the puzzle is in the .sln solution file that makes sure the projects are nicely grouped together. There’s two parts to the solution that makes this work:

The Guids are the project guids referencing the projects that needs to be grouped as a universal project.

Microsoft only gives you the tooling to do Windows Store and Windows Phone Universal projects. However knowing how this now works, it makes you wonder if you can manually go add the Shared Project reference to for example your WPF application, and add it to the solution under the nested project parts. And in fact you can! Below is an example of the ArcGIS Runtime Toolkit (which today uses linked files to compile for Store, Phone and WPF): Note how ‘Generic.xaml’ is the only file not shared, because the UI has been optimized for each platform, and also WPF XAML isn’t compatible with Store and Phone. Again the Universal Apps makes this really easy to manage files you don’t want shared.

And the context switcher now also shows a third option:

In fact I can make a shared project that’s used in a Windows Store, Windows Phone, WPF, Silverlight, Console, Windows Forms etc etc! Of course at some point the platforms are so different the amount of code that is shared will be reduced, but I find this as a great alternative to PCL without the limitations of PCLs.

Talking to the people behind this feature, this functionality does come with a warning: First of all this hasn’t been extensively tested, so you might hit issues with it. Another thing to be careful with is build actions. For example if you want to share image Assets, you want to set the build action to ‘Content’ for Windows Phone and Windows Store, but in WPF you want to set it to ‘Resource’, and this naturally isn’t supported (but you can still used linked files in the individual projects to work around this).