Creating and retrieving resources in Windows Runtime apps

 

The Windows 8 operating system introduces a new resource model for Windows 8.x 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 8.x Store apps.

Resources in Windows 8.x 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 8.x 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

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 8.x 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

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.

Warning

Although the System.Resources.::..ResourceManager class is included in the .NET for Windows 8.x 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.

Creating resource files

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 8.x 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 8.x 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 8.x 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").

Deploying resource files

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.

Retrieving resources from resource files

To retrieve resources in a Windows 8.x 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 8.x 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.

ResourceManager member

Equivalent member of ResourceLoader or other Windows Runtime type

ResourceManager.::..GetString(String)(String^)(String)(String)

Windows.ApplicationModel.Resources.ResourceLoader.GetString(String)

ResourceManager.::..GetString(String, CultureInfo)(String^, CultureInfo^)(String, CultureInfo)(String, CultureInfo)

Windows.ApplicationModel.Resources.Core.ResourceMap.GetValue(String, ResourceContext)

ResourceManager.::..ResourceManager(String, Assembly)(String^, Assembly^)(String, Assembly)(String, Assembly)

Windows.ApplicationModel.Resources.ResourceLoader.ResourceLoader()

-or-

Windows.ApplicationModel.Resources.ResourceLoader.ResourceLoader(String)

A simple "Hello World" example

The following is a simple example of a Windows 8.x 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);
}

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Example.Run(outputBlock)
End Sub

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);

    }
}

Imports System.Globalization
Imports Windows.ApplicationModel.Resources
Imports Windows.ApplicationModel.Resources.Core
Imports Windows.UI.Xaml.Controls

Public Class Example
    Public Shared Sub Run(outputBlock As Windows.UI.Xaml.Controls.TextBlock)
        outputBlock.Text += String.Format("{1}The current culture is {0}.{1}",
                                          CultureInfo.CurrentCulture.Name, vbCrLf)
        Dim rl As ResourceLoader = New ResourceLoader()

        ' Display greeting using the resources of the current culture.
        Dim greeting As String = rl.GetString("Greeting")
        outputBlock.Text += String.Format("{0}{1}",
                                          If(String.IsNullOrEmpty(greeting), "Здравствуйте", greeting),
                                          vbCrLf)

        ' Display greeting using fr-FR resources.
        Dim ctx As ResourceContext = New Windows.ApplicationModel.Resources.Core.ResourceContext()
        ctx.Languages = {"fr-FR"}

        Dim rmap As ResourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources")
        Dim newGreeting As String = rmap.GetValue("Greeting", ctx).ValueAsString()

        outputBlock.Text += String.Format("{1}{1}Culture of Current Context: {0}{1}",
                                          ctx.Languages(0), vbCrLf)
        outputBlock.Text += String.Format("{0}{1}", If(String.IsNullOrEmpty(newGreeting),
                                                       greeting, newGreeting), vbCrLf)
    End Sub
End Class

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!

See Also

Resources in Desktop Apps
Visual Studio resource editors