Sharing XAML UI
[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]
In this section we discuss sharing XAML UI between your Windows Phone 8 and Windows Store apps. We outline the reasons why sharing at this layer in your app is less effective than sharing app logic, and discuss the use of user controls to share some UI between your apps. The guideline is to build your UI for each app separately to embrace the design guidelines for each and deliver the best experience possible to the user. There are similarities in the building blocks used to build UI for a XAML app. These are discussed in XAML controls comparison between Windows Phone 8 and Windows 8.
This topic contains the following sections.
Limitations of sharing XAML UI
The following factors make it a challenge to share XAML UI between your apps.
XAML on Windows Phone 8 and XAML on Windows 8 is not binary compatible. As stated earlier, the controls you use to build your UI on each platform are similar. They are similar in name, behavior, and the programming interfaces, or syntax, they expose. However, they are implemented specifically for each platform.
Namespace prefixes are different in XAML for Windows Phone 8 and XAML for Windows 8. This is illustrated by looking at the namespaces included in a basic page when you create it from scratch.
Windows Phone 8
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
Windows 8
```
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Win8App"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
```
Comparing these namespace imports, you can see the subtle but significant difference in how a namespace is imported. In Windows Phone 8, imported namespaces are prefixed with clr-namespace:. In Windows 8 imported namespaces are prefixed with using:. This makes it difficult to use the same XAML, unless you can import namespaces using the same syntax.
- XAML doesn’t support conditional compilation. As shown in Conditional compilation with preprocessor directives, conditional compilation is a useful technique for handling platform differences by compiling in a code path that targets a particular platform, and another code path when compiling for another platform. This makes it difficult to share a XAML page between both platforms, because you can’t address the previous issue by simply conditionally compiling in namespace imports that use clr-namespace for Windows Phone 8 and using: for Windows 8.
This shouldn’t be seen as a complete roadblock for sharing between Windows Phone 8 and Windows 8. The clear guidance is to design and build your UI separately for each platform, embracing the design guidelines for each. It is technically possible to circumvent these obstacles. You could create your UI during page initialization from code. You could load platform-specific XAML from resources at runtime and inject it as a string into the page. However, none of these techniques scale and they make the construction of your core asset—how your app looks to your user—a tedious and error-prone task. Your code sharing investment will give you a much larger return further down your app stack, by trying to share app logic, data models, viewmodels, etc.
Sharing XAML UI using a UserControl
One technique for sharing UI that can be of use in some circumstances is to isolate parts of your UI into user controls and attempt to share those. Windows Phone 8 and Windows 8 both support XAML user controls. A UserControl is a UI control that you define, and which is composed of existing UI elements, and contains its own logic. You can place controls that you define into your UI just like you would any other control available on the platform. For info about the UserControl class in Windows Phone 8, see System.Windows.Controls..::.UserControl. For info about the UserControl class in Windows 8, see Windows.UI.Xaml.Controls..::.UserControl.
The following table shows the XAML that’s created when you add a new UserControl to your Windows Phone 8 app, and the XAML that’s created when you add a new UserControl to your Windows Store app. The imported namespace are the same, if you omit the local namespace from the Windows 8 control. You can do that if you don’t reference any local resources in the control. The Windows Phone 8 control also defines Font, Background, and Foreground properties for the control. These are set to values that come from styles that ship with Windows Phone. These also could be removed, or replaced with something more generic. It also would be simple to set these in code-behind.
Windows Phone 8
<UserControl x:Class="MyApp.Controls.WP8.MyControl"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
</Grid>
</UserControl>
Windows 8
<UserControl
x:Class="MyApp.Controls.Win8.MyControl"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Controls.Win8"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
</Grid>
</UserControl>
If we remove the platform-specific features in these XAML examples, we have the following.
<UserControl
x:Class="MyApp.Controls.Shared.MyControl"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
</Grid>
</UserControl>
We’ve changed the namespace to signify that this control is shared. This XAML will run on both Windows Phone 8 and Windows 8 and could be shared if the namespace and control name was the same. This limits what you can implement in a shared user control. Here’s the approach you should take for sharing a UserControl between Windows Phone 8 and Windows 8. The following steps show you how to share XAML UI using a UserControl.
In Visual Studio, add a new UserControl to either one of your projects.
Change the namespace to one that indicates this will be shared, for example, MyApp.Shared.Controls. You’ll also need to update the Class entry in the XAML for the UserControl to qualify the name with this new namespace.
Open the XAML for the UserControl and modify it to look like the stripped-down XAML shown in the preceding code.
Add your UI elements into the control. In this example, we’ll add a TextBox, a TextBlock, and a Button. Font and colors have been hardcoded for simplicity. The updated XAML is shown in the following snippet.
<UserControl x:Class="MyApp.Shared.Controls.MyControl" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="480" d:DesignWidth="480"> <Grid x:Name="LayoutRoot" Background="Black"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBox x:Name="InputText"/> <Button x:Name="SayHelloButton" Click="SayHelloButton_Click_1" Content="Say Hello!"/> <TextBlock x:Name="OutputText" FontSize="28" Foreground="White"/> </StackPanel> </Grid> </UserControl>
Build and test the control by dropping it onto a page in your app. To use the control, you will have to import the namespace you chose. In your Windows Phone 8 app, import the namespace by adding xmlns:sharecontrols="clr-namespace:MyApp.Shared.Controls" to the <UserControl> start tag of the XAML page. Similarly, for your Windows Store app, import the namespace by adding xmlns:sharecontrols="using:MyApp.Shared.Controls" to the <UserControl> start tag of the XAML page.
Now use the control on the page.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <sharecontrols:MyControl /> </Grid>
At this point, you have created the UserControl. The next step is to share it in both projects.
In Solution Explorer, right-click the UserControl, and then select Exclude From Project. This removes the control from the project but it is still on disk.
Add the control back to your project by right-clicking the project in Solution Explorer, and then select Add | Existing Item.
Select the MyControl.xaml and MyControl.xaml.cs files in the dialog box, and then select Add as Link. This adds both files back into your project as linked files. You should verify that page on which you dropped the control before works once again.
Repeat the preceding two steps for your other project, adding the control into that project as a linked file.
This project won’t build because the MyControl.xaml.cs file contains references to namespaces that are platform-specific. You can use conditional compilation to add the correct namespaces for this project type. Here’s an example of what the namespace declaration section looks like when the control has been added to the Windows Phone 8 project and to the Windows Store project. The code also contains the implementation of the button’s Click event handler.
using System; using System.Collections.Generic; using System.Linq; using System.Net; #if NETFX_CORE using Windows.UI.Xaml.Controls; using Windows.UI.Xaml; #else using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using Microsoft.Phone.Controls; using Microsoft.Phone.Shell; #endif namespace MyApp.Shared.Controls { public partial class MyControl : UserControl { public MyControl() { InitializeComponent(); } private void SayHelloButton_Click_1(object sender, RoutedEventArgs e) { OutputText.Text = String.Format("Hello {0}", InputText.Text); } } }
Build, run, and test both apps to verify that the control works for both.
The preceding code example shows you how a user control can be built for both Windows Phone 8 and Windows 8. However, due to the limitations called out at the beginning of this discussion, the technique is limited to basic user controls. In addition to those limitations, you should consider the guideline to always build your user experience to suit the target platform. Sharing XAML controls is possible but limited. A good candidate for this kind of sharing is UI you want to display in a pop-up window or other widgets that you want to share because they typically will be composed of basic UI elements with no complex XAML and with simple styling.
See Also
Other Resources
Build 2012: How to Leverage your Code across Windows Phone 8 and Windows 8