Managing XAML Resources in Universal Windows Phone 8.1 and Windows 8.1 Apps

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:

universalsolution

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:

universal-xamlresourcesFrom 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:

sharedpage-wp

Windows:

sharedpage-win

Finding Default Styles for Windows Phone 8.1 and Windows 8.1 XAML Controls

When you want to retemplate a XAML control, you can usually create a copy of its default template by right clicking the control within the Visual Studio Designer or Document Outline windows and selecting “Edit Template” or “Edit Additional Templates”:

xaml-edittemplatecopy

Clicking “Edit a Copy…” will allow you to name the new style and select where you want to put it. Visual Studio will copy over the default properties and point your control to use the new style.

In some situations, it may be difficult or impossible to select the control you wish to edit through the designer. Or, such as with this ContentDialog control, the option may be disabled:

xaml-edittemplatedisabled

For those situations, you can find the default styles for all Windows Phone 8.1 XAML controls in the following file:

C:\Program Files (x86)\Windows Phone Kits\8.1\Include\abi\Xaml\Design\generic.xaml

The equivalent file for Windows 8.1 XAML controls is located at:

C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\xaml\design\generic.xaml

From there, you can copy the styles and templates you need into your app and modify them as necessary.

Fixing jumpy ListBox scrolling in WP7 Mango

Update October 14, 2011: If you are using Buttons in your item templates this may cause some issues. See the comments at the bottom of the page for more information and a potential workaround.

A few days ago I tweeted about a ListBox scrolling issue I found with WP7 Mango when using item templates that have different heights. I first noticed this issue when using the Silverlight Toolkit’s LongListSelector control, but I found that it also applies to the standard ListBox control (which the Mango version of the Silverlight Toolkit uses internally to display data) whenever list items have different heights (e.g., wrapped text, list headers/footers, etc.).

In short, the issue is that after tapping/selecting an item in the list, scrolling becomes extremely jumpy. It’s a bit hard to describe — it’s not just a matter of poor performance, the list scroll position will actually jump up or down as you try to scroll through the list.

I found a relevant bug report on the SL Toolkit’s issue tracker here. At first I thought the issue was caused by selecting an item within the ListBox but I found that deselecting the item didn’t fix the scrolling behavior.

After doing some further testing I discovered that the issue was triggered whenever the ListBox (or a control displayed within the ListBox) gained focus. Setting focus to another control on the page seems to fix the issue completely.
Continue reading Fixing jumpy ListBox scrolling in WP7 Mango

Using remote images with secondary live tiles in WP7 Mango

I’ve seen a few posts on Twitter and this blog post by Jeff Wilcox about the issues with using a remote image on secondary live tiles, so I thought it might be useful to share the workaround I developed for a new WP7 application I have been working on that makes heavy use of secondary tiles.

In short, the issue with using remote URIs for the BackgroundImage or BackBackgroundImage properties of secondary live tiles is that the tiles will disappear after restarting the phone. Worse, the tile still appears in the ShellTile.ActiveTiles list as though the tile is still pinned. This issue is mentioned in a few parts of the documentation, including here:

When creating a secondary Tile, the BackgroundImage and the BackBackgroundImage images must be created using a local resource.

I did some testing and determined that the issue is only caused by using a remote image URI during the initial tile creation — any tile updates that occur later on can use remote URIs without any trouble. In fact, you can update the tile with a remote URI immediately after creating it and the tile will still appear after the phone is restarted. (Note that the image displayed after a restart will be the static, local image and not the remote image. For my app, the tiles are regularly updated via push notifications but you could also update the tiles from within your app or background agent, etc.)
Continue reading Using remote images with secondary live tiles in WP7 Mango

WP7 Application Crash Reporter

Update Feb. 26, 2011: Crash logger code has been modified to provide more details, including the OS version, current culture, current XAML page, and whether the app is obscured or locked.

Recently I found Andy Pennell’s LittleWatson Class, which is designed to log and report any unexpected crashes in your WP7 app. This can provide extremely useful data about problems your users have experienced and, if you tend to run your app without debugging enabled, crashes that occur during development.

Andy’s code is designed to send error reports via e-mail, but I’d prefer something a bit less intrusive. For Remote, I decided to write a class similar to LittleWatson that would submit the error reports to a script running on my web server.
Continue reading WP7 Application Crash Reporter

Simple Installation Tracking for WP7 Apps

When I first started developing Remote, Microsoft had not yet provided a way for developers to see how many downloads their apps were getting. Microsoft now provides app download statistics via the App Hub, but the data is delayed by 6 days and only shows new installations – app upgrade statistics are not available. With this in mind, I decided to create a simple installation tracking system to monitor how well my app was doing in real time.

Looking through the App Hub Forums, I found a few other sales tracking systems. This one, based on Google AppEngine, tracks not only installations but usage activity and phone model and manufacturer information. This one is based on the Silverlight Analytics framework and uses Google Analytics for reporting.

My tracking code is much simpler and does not require any third-party frameworks, but it only reports new installations and upgrades. If you need to track feature usage information, you might be better off using one of the other solutions rather than trying to modify this code to your needs. Also, it’s worth noting that retrieving device manufacturer and model information requires an additional capability listing (“phone identity”) which may deter customers from wanting to try your app.
Continue reading Simple Installation Tracking for WP7 Apps