Dela via


How to load string resources (XAML)

You can load string resources from objects such as resource files, libraries, controls, and app packages and manifests.

Loading strings from resource files

String resources are authored in resource files and referred to by using resource identifiers. For a basic introduction to loading string resources, see Quickstart: Using string resources.

Most apps need only a single default resource file per language (<language>/Resources.resw), and they can refer to their resources by using a relative path to keys within that file (for example /String1). But in some applications it is appropriate to separate resources into multiple resource files in order to provide separation of components.

For example:

Filename:

Strings/en-US/Errors.resw

A reference from markup

<TextBlock x:Uid="/Errors/AlreadyRegistered"></TextBlock>

A reference from code

var resourceLoader =  ResourceLoader.GetForCurrentView("Errors");
String arstring = resourceLoader.GetString("AlreadyRegistered");

The resource identifier is of the form /ResourceFileName/StringName. Note that the resource filename does not include the extension or the folder path. Therefore all resource filenames need to be unique in a component or project.

Note about Property identifiers:

The resource Name can only be qualified with property identifiers supported by all controls that reference the resource. If a property specified in the resource file cannot be assigned to a referencing control, a runtime exception occurs.

The GetString method cannot retrieve resources qualified with a property identifier.

Loading strings from libraries or controls

Apps often have multiple components, or take dependencies on libraries such as .NET portable class libraries, other compatible class libraries, and control libraries.

Whenever possible, controls and components should try to reduce the number of resources and rely on the app to provide them. When a library does need to provide resources, it should allow apps to replace those resources as an input. This may be necessary if the library does not have the same extent of localization as the app using it.

The control should display custom strings passed into it exactly as given and, where possible, let the app handle localization.

Components or library files are typically added into a subfolder of the package they are included in during the build process, similar to their string resources. Their resource identifier usually takes the following form:

ClassLibraryOrAssemblyName/ResourceFileName/StringName

Programmatically, libraries can also get their own ResourceLoader for their resources. For example, the following code illustrates how a library or component can get a ResourceLoader for its own resource file:

ResourceLoader RL = new Windows.ApplicationModel.Resources.ResourceLoader("ContosoControl/Resources");
RL.GetString("loadingStr"); // which came from ContosoControl's Resources.resw

Loading strings from other packages.

Resources for each app package are separately managed and accessed through separate top level ResourceMaps that are accessible from the current ResourceManager. Within each package, various components can have their own **ResourceMapSubtrees.

Framework packages can access their own resources with a more absolute resource identifier URI. For more details on ms-resource: and ms-appx: schemes, see URI schemes.

Loading strings from the app manifest.

All displayable strings and logos in the manifest are localizable. Logos can also be tailored for scale and high contrast mode. String references can be added in the place of a hardcoded string, by placing an ms-resource: scheme-specified URI into the manifest (this is usually done in the Visual Studio tabbed UI for editing the appxmanifest). For example, ms-resource:String1 refers to a string called String1 in the Resources.resw resource file, while ms-resource:/ManifestStrings/Shortname refers to a string called Shortname in the ManifestStrings.resw resource file.

Loading strings for a specific language or context.

The default ResourceContext, an object obtained from the ResourceManager, represents the current state to which resources are matched. The ResourceContext contains all the various qualifier values for the current user and machine. Although each qualifier can be overridden, it is not recommended that you override them. Most qualifiers have a system data provider, which in some cases is best altered through a separate API (that is, PrimaryLanguageOverride), or best left unchanged.

See How to name resources using qualifiers for details on the various qualifiers.

The ResourceManager maintains the default context object against which resource lookups are done. In some particular cases, being explicit about the language, scale or other context qualifier when the app loads resources may be helpful. For example, an app might allow a user to select an alternative language for tooltips or error messages. Lookups can specify their own explicit overridden context object, to affect which resource is chosen. To specify an explicit context, where the Languages property is deliberately overridden:

//using Windows.ApplicationModel.Resources.Core;

var context = new ResourceContext(); // deliberately not using getForCurrentView()
context.Languages = new string() {"fr-fr"}; 
ResourceMap resourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
String str = resourceMap.GetValue("string1", context).ValueAsString;

Another technique you can use is to call ResourceContext.SetGlobalQualifierContext before calling ResourceContext.GetForCurrentView. For the language scenario you'd set the language qualifier to a new value. The difference if you do this is that the qualifier and context change now applies to all resource lookups, not just the specific ResourceContext you created for use for the single GetValue call. See also ApplicationLanguages.PrimaryLanguageOverride.

Events and context changes.

An app might still be running when the system changes one of the factors that influence the resource context. This results in a different set of qualifiers being used. Various system changes invoke events on the ResourceContext object.

In apps that use XAML, the process of updating the displayed page with new resources is complicated by the fact that handlers for these events are often called on a different thread than the UI thread. The following partial sample illustrates a way to listen for the change event and to update text on the main page. Note that:

  • In the MainPage constructor, the event handler qualifiers_MapChanged is set to be called when the resource qualifiers change.
  • The event handler qualifiers_MapChanged ensures that the method UpdateTextBlocks is called using RunAsync so it can update UI without violating a thread boundary.
  • The method UpdateTextBlocks does the work of loading the newly appropriate resource strings and updating the text blocks on the main page.
using Windows.ApplicationModel.Resources.Core;
using Windows.ApplicationModel.Resources;
using Windows.Foundation.Collections;

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        // Listen for event when the resource qualifiers change.
        var qualifiers = ResourceContext.GetForCurrentView().QualifierValues;
        qualifiers.MapChanged += new MapChangedEventHandler<string, string>(qualifiers_MapChanged);
    }

    // Event handler for change in resource qualifiers.
    private async void qualifiers_MapChanged(IObservableMap<string, string> sender, IMapChangedEventArgs<string> @event)
    {
        var d = Greeting.Dispatcher;
        if (d.HasThreadAccess)
        {
            UpdateTextBlocks();
        }
        else
        {
            await d.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => UpdateTextBlocks());
        }
    }

    // Update text blocks on the main page.
    private void UpdateTextBlocks()
    {
        // Replace the Text properties of text blocks on the main page with the appropriate resource strings.
        ResourceLoader resourceLoader = new ResourceLoader();
        Greeting.Text = resourceLoader.GetString("Greeting");
        Farewell.Text = resourceLoader.GetString("Farewell");
    }
    ...
}

Windows.ApplicationModel.Resources.ResourceLoader

Windows.ApplicationModel.Resources.Core.ResourceContext

Windows.ApplicationModel.Resources.Core.ResourceManager

Windows.ApplicationModel.Resources.Core.ResourceMap

Windows.Globalization.ApplicationPreferences.PrimaryLanguageOverride

Features and restrictions by context

How to name resources using qualifiers

Roadmap for Windows Runtime apps using C# or Visual Basic