apps2go
apps2go

Reputation: 198

How do I access Resources.resw strings in a Winui3 TemplateStudio app

The WinUI for Desktop Template Studio template contains a file Resources.resw file in the project folder Strings/en-us. The ShellPage has XAML Uid properties which map to keys in this file for navigation page titles. I am trying to store other localized strings in this file and access them in code.

I am using the following code to extract the string when a particular page is loaded:

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

        Loaded += (s, e) =>
        {
            var rl = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
            App.CurrentPageTitle = rl.GetString("TransactionDetailPage.Title");
        };
    }
}

However, I am getting the following runtime error and despite much googling have been unable to find a solution.

System.Runtime.InteropServices.COMException:
Resource Contexts may not be created on threads that do not have a CoreWindow. (0x80073B27)

I would appreciate any help solving this problem.

Upvotes: 2

Views: 931

Answers (2)

Abdessattar
Abdessattar

Reputation: 139

A slight adjustment to the answer by @Andrew KeepCoding to allow for shorter keys when looking for localized resources defined in the calling assembly:

I use the ResourceManager instead of ResourceLoader so that I can access the main resource map as well as any other sub-map within the application.

using Microsoft.Windows.ApplicationModel.Resources;

public static class ResourceExtensions
{
    private static readonly ResourceMap Strings = new ResourceManager().MainResourceMap;

    public static string? GetLocalized(this string? value)
    {
        if (value == null)
        {
            return value;
        }

        var localized = Strings.TryGetValue(value);
        return localized != null ? localized.ValueAsString : value;
    }

    public static string? GetLocalizedMine(this string? value)
    {
        if (value == null)
        {
            return value;
        }

        var assemblyName = Assembly.GetCallingAssembly().GetName().Name;
        var subMap = Strings.GetSubtree($"{Assembly.GetCallingAssembly().GetName().Name}/Strings");
        if (subMap == null)
        {
            Debug.WriteLine($"Resource map for assembly `{assemblyName}` does not exist.");
            return value;
        }

        var localized = subMap.TryGetValue(value);
        return localized != null ? localized.ValueAsString : value;
    }
}

Upvotes: 0

Andrew KeepCoding
Andrew KeepCoding

Reputation: 13666

The Template Studio should create this class:

ResourceExtensions.cs

using Microsoft.Windows.ApplicationModel.Resources;

namespace TemplateStudioWinUI3LocalizerSampleApp.Helpers;

public static class ResourceExtensions
{
    private static readonly ResourceLoader _resourceLoader = new();

    public static string GetLocalized(this string resourceKey) => _resourceLoader.GetString(resourceKey);
}

so you should be able to:


Loaded += (s, e) =>
{
    App.CurrentPageTitle = "TransactionDetailPage.Title".GetLocalized();
}

Upvotes: 2

Related Questions