Universal apps for Windows 8.1 and Windows Phone 8.1 allow you to share both code and XAML resources between desktop and phone versions of an application. Anything contained in the “Shared” pseudo-project gets compiled individually into each platform-specific project:
This is unlike Portable Class Libraries where a single assembly is compiled and shared between the projects that use it. Files in the “Shared” project are included and compiled directly alongside the platform-specific projects’ own files.
This enables some nice features. For instance, you can write conditional code blocks (using #if
) to change application behavior between different platforms. New Universal apps have the WINDOWS_PHONE_APP
and WINDOWS_APP
symbols defined for this purpose:
#if WINDOWS_PHONE_APP
Debug.WriteLine("Hello from Windows Phone!");
#elif WINDOWS_APP
Debug.WriteLine("Hello from Windows!");
#endif
Sharing XAML Resources
XAML resources are a bit different. It isn’t currently possible to have conditional XAML within a single file (although there is at least one effort being made toward that goal), so you either have to share the entire file or make a separate copy for each platform.
If you want to define app-wide XAML resources (outside of the context of a particular page or control) you might typically do that in App.xaml. But if you share App.xaml/App.xaml.cs between both the phone and desktop platforms (and you should!) then it becomes impossible to have different app-wide XAML resources on each platform.
Merged ResourceDictionaries
You can work around this issue by merging in platform-specific ResourceDictionaries within App.xaml:
<Application
x:Class="TestUniversalXAML.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestUniversalXAML">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/AppResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
In this example, the app will look for a file called Themes/AppResources.xaml and merge it into its main ResourceDictionary. This file could be either a shared or platform-specific file, and you can specify additional ResourceDictionaries to merge in as well. (This can get a bit tricky, however, if you need to reference static resources across different merged files, so it’s usually best to try to keep things contained in a single file if possible.)
For our needs, we’ll simply add a new Resource Dictionary with the specified name in each project. (Also, it’s worth noting that Resource Dictionary is now included in the list of file templates within Visual Studio, making this even easier.)
Here’s what the VS solution looks like with the platform-specific XAML resource dictionaries underlined in red:
From there, just put any XAML resources you need in the platform-specific AppResources.xaml file and they will become available throughout your application. Any styles or other resources will work in the Visual Studio designer window and the new XAML static resource autocompletion will continue to work exactly as you’d expect.
Easier Page and User Control Sharing
This also makes it easier to share pages and user controls between platforms. You can reference platform-specific styles, DataTemplates, or any other static resource from shared pages/controls as long as a resource exists with the same name on each platform.
In most situations, this will probably be a better solution than modifying control properties from conditional code in the code behind. Not only does it help maintain the separation of code and layout, but it also works perfectly within the Visual Studio designer.
Here’s an example with a shared page. The style MyTextBlockStyle
sets the text color to red on Windows Phone and green on Windows. (By the way, you can switch between viewing within the context of Windows or Windows Phone by using the drop-down box I’ve underlined in red.)
Windows Phone:
Windows: