Creating and retrieving resources in Windows Store apps

The Windows 8 operating system introduces a new resource model for Windows Store apps that replaces the hub-and-spoke model common to .NET Framework desktop apps. This topic discusses this new resource model and explains how to create, deploy, and retrieve resources in Windows Store apps.

.NET Framework desktop apps use a hub-and-spoke model for packaging and deploying resources. Typically, resources for the app's neutral culture (the culture whose resources are used if no localized resources are available) are embedded in the app's main executable. Localized resources for each additional culture are embedded in a stand-alone satellite assembly that contains only resources and no executable code.

In contrast, Windows Store apps use a single resource file. This file is called a package resource index (PRI) file and stores resources for all languages, cultures, and scale factors.

Important note Important

Resource fallback rules determine which resources are loaded if the localized resources for a specific culture or the current culture cannot be found.

In desktop apps, you can use either text files or XML (.resx) files to create resources. The Resource File Generator (Resgen.exe) is used to compile these files into binary resources (.resources) files. You use the compiler to embed the resources of the neutral culture in the main app assembly, and you use the Assembly Linker (AL.exe) to embed all other localized resources into satellite assemblies. You can then retrieve individual resources by using the System.Resources.ResourceManager class, or enumerate resources by using the ResourceReader class.

In Windows Store apps, you use .resw files to create resources. Despite the difference of file extension, the .resw file format is identical to the .resx file format, except that .resw files may contain only strings and file paths. You can use the Visual Studio resource editors to create and edit resources. At compile time, all the .resw files for an app are packed into a single PRI file by the MakePRI utility and included with the app's deployment package. At run time, the Windows.ApplicationModel.Resources.ResourceLoader class and the types in the Windows.ApplicationModel.Resources.Core namespace provide access to app resources.

Important note Important

Although the Resource File Generator (Resgen.exe) is primarily for use in desktop apps, you can also use this tool to decompile satellite assemblies into .resw files, which can then be compiled into a PRI file.

Caution note Caution

Although the System.Resources.ResourceManager class is included in the .NET for Windows Store apps, we do not recommend its use. Use ResourceManager only in libraries that are developed as Portable Class Library projects and that target multiple platforms.

Visual Studio's resource editors provide the easiest and most convenient way to create a .resw file. These editors provide a user interface that hides the underlying XML file format of the .resw file. Using Visual Studio to create and edit a resource file has two main advantages:

  • It eliminates the need to create a resource file manually and to ensure that its XML format is valid.

  • It handles the process of using the MakePRI utility to compile the resource, pack it into a PRI file, and include it in the app's deployment package.

To create a resource file for a Windows Store app, in Solution Explorer, open the shortcut menu for the project, choose Add, New Item, and then choose Resources File from the list of items.

In desktop apps, you use the NeutralResourcesLanguageAttribute attribute to define your app's neutral culture. In Windows Store apps, this attribute is ignored when the PRI file is created and when the Windows ResourceLoader class is used to extract resources.

In Windows Store apps, you designate the names of localized resource files by creating a folder to store the resources and images of a supported culture. You can then describe the resource by using the culture name (such as "ko-kr") followed by the default resource name and resource file extension (such as "ko-kr\Resources.resw").

Visual Studio handles all the details of app deployment for resource files that are part of a Visual Studio project. It automatically generates a configuration file for all resources that are part of a project, uses the MakePRI tool to include the resources in a single PRI file, and places the PRI file in the app's deployment package.

Because all resources are included in a single PRI file instead of a collection of individual files, modifying an existing resource file or adding support for a new localized culture by adding a resource file requires the entire app to be rebuilt and redistributed.

To retrieve resources in a Windows Store app, you instantiate a Windows Runtime Windows.ApplicationModel.Resources.ResourceLoader object or one of the types in the Windows.ApplicationModel.Resources.Core namespace. Although the .NET Framework System.Resources.ResourceManager class is supported in Windows Store apps, we do not recommend its use. Use ResourceManager only when you develop Portable Class Library projects that target multiple platforms. The following table lists ResourceManager members and their simple equivalents in the Windows.ApplicationModel.Resources.ResourceLoader class or the types in the Windows.ApplicationModel.Resources.Core namespace.

The following is a simple example of a Windows Store app that displays localized strings. Its neutral culture is Russian (Russia), but it also includes resources for the English (United States) and French (France) cultures. If the app is run on a system whose current culture is English (United States), it displays a greeting in English; otherwise, it displays the default Russian greeting. Finally, regardless of the current culture, it uses the Windows.ApplicationModel.Resources.Core.ResourceContext and Windows.ApplicationModel.Resources.Core.ResourceMap objects to display a greeting in French.

To display output to a TextBlock control, the example requires adding the following <TextBlock> tag to BlankPage.xaml:

    <Grid Background="{StaticResource PageBackgroundBrush}">
       <TextBlock x:Name="outputBlock" />
    </Grid>

The application code is then called from the BlankPage class constructor as follows:

public BlankPage()
{

    InitializeComponent();
    Example.Run(outputBlock);
}

The example requires that you create the following resources:

  • A Russian language resource named "Greeting" whose value is "Привет!". The string should be added to a resource file named Resources.resw at the project's root level.

  • An English language resource named "Greeting" whose value is "Hi there!". To create the resource file, add a folder named en-US to your project, and then add a resource file named Resources.resw to the folder.

  • A French language resource named "Greeting" whose value is " Bonjour!". To create the resource file, add a folder named fr-FR to your project, and then add a resource file named Resources.resw to the folder.

The following example displays the appropriate localized strings in the TextBlock control.

using System;
using System.Globalization;
using Windows.ApplicationModel.Resources;
using Windows.ApplicationModel.Resources.Core;
using Windows.UI.Xaml.Controls;

public class Example
{
    public static void Run(Windows.UI.Xaml.Controls.TextBlock outputBlock)
    {
        outputBlock.Text += String.Format("\nThe current culture is {0}.\n", CultureInfo.CurrentCulture.Name);
        ResourceLoader rl = new ResourceLoader();

        // Display greeting using the resources of the current culture. 
        string greeting = rl.GetString("Greeting");
        outputBlock.Text += String.Format("{0}\n", String.IsNullOrEmpty(greeting) ? "Здрауствуйте" :  greeting);


        // Display greeting using fr-FR resources.
        ResourceContext ctx = new Windows.ApplicationModel.Resources.Core.ResourceContext();
        ctx.Languages =  new string[] { "fr-FR" } ;

        ResourceMap rmap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
        string newGreeting = rmap.GetValue("Greeting", ctx).ValueAsString();

        outputBlock.Text += String.Format("\n\nCulture of Current Context: {0}\n", ctx.Languages[0]);
        outputBlock.Text += String.Format("{0}\n", String.IsNullOrEmpty(newGreeting) ? greeting : newGreeting);

    }
}

When you compile and run the application, it displays output like the following on a system whose culture is en-US:

The current culture is en-US.
Hi there!

Culture of Current Context: fr-FR
Bonjour!
Show:
© 2014 Microsoft