WInUI3関連記事
https://tera1707.com/entry/2022/02/06/144447#WinUI3
やりたいこと
WPFの時にも、文字列リソースを登録してxamlやコードから使ったが、同じことをWinUI3アプリでもやりたい。
やりかた
MS公式情報の、下記を元に対応を行う。
※このページはUWPアプリ向けだからか、WinUI3アプリでそのままやろうとしてもうまくいかなかったので、詰まったところ中心にメモする。
手順
各国言語ごと(ja-JP、en-US等)にResource.reswファイルを作成する
VisualStudioで、WinUI3プロジェクトの中にStrings
フォルダを作成する。
さらに、Strings
フォルダの中に言語の名前毎にフォルダを作成する。下図のようなイメージ。
各言語のフォルダに、リソースファイル(.resw)を追加する。
下図のようなイメージ。
リソースの値を定義する
追加したResource.resw
に、リソースを追加する。
リソースを定義する際は、対象のコントロールの、値をセットするプロパティに合わせて、定義をする。
<TextBlock>
のText
プロパティに使うなら「リソース名.Text」に「あいうえお」などを定義する。<Button>
のContent
プロパティに使うなら「リソース名.Content」に「あいうえお」などを定義する。<Button>
のHeight
プロパティに使うなら「リソース名.Height」に「150」などを定義する。<Grid>
のBackground
プロパティに使うなら「リソース名.Background」に「Yellow」などを定義する。
という感じでリソースを作る。
xamlでリソースを使う
各コントロールに、x:Uid="リソース名"
と書く。下記のような感じ。
<StackPanel x:Uid="MyStackPanel"> <TextBlock x:Uid="MyTextBlock"/> <Button x:Uid="MyButton"/> </StackPanel>
これを実行すると、下図のような感じになる。
※見づらいが、ボタンがHeight=150分の高さで置かれている。
これで、xamlで使う分にはOK。
【注意】
リソースを使ったコントロールに存在しないプロパティのリソースを定義してしまったとき(例えば、ButtonにはTextプロパティがないのに、上で作ったMyTextBlock
を使ってしまったときなど)は、下記のような例外がInitializeComponent()で起きる。
Microsoft.UI.Xaml.Markup.XamlParseException
XAML parsing failed.
OSの言語設定に追従して、使うreswを切り替えるようにする
リソースの使い方として、OSの言語の設定が日本語のときはja-JPフォルダの下に作ったResources.resw、英語のときはen-USの下のResources.reswを使ってほしいと思うが、xamlで、x:Uid
にリソースをセットするだけではそのようにはなってくれない。
パッケージプロジェクトに含まれる「Package.appxmanifest」に、使う言語の設定を行ってやる。→参考
プロジェクト作成直後は
<Resources> <Resource Language="x-generate"/> </Resources>
となっている部分を、
<Resources> <Resource Language="ja-JP"/> <Resource Language="en-US"/> </Resources>
とする。使う言語の分だけ並べる。
これで、OSの言語設定に合わせて、使うリソースを変えてくれる。
C#コードでリソースを使う
ここがUWPのローカライズ資料のままやってもうまくいかなかった。
下記のようにすると、うまくいった。
// using Microsoft.Windows.ApplicationModel.Resources; var loader = new ResourceLoader(); var str = loader.GetString("SimpleText"); // これで、上で定義した「単純な文字列リソース」が取れる
リソース名.プロパティ名
で定義した奴の場合は、下記のようにする。
var loader = new ResourceLoader(); var str = loader.GetString("MyButton/Content"); // これで、上で定義した「ボタン名称」が取れる
※リソース名とプロパティ名の間の「.」を、「/」に置き換えること。
【注意】
UWPのローカライズ資料の通りに、下記のようにしてコードからリソース取得しようとすると、例外が起きる。
System.Runtime.InteropServices.COMException
CoreWindow のないスレッドにリソース コンテキストは作成できません。 (0x80073B27)
添付プロパティに使うリソースを定義し使う
ここまで、コントロールが持っているプロパティに使うためのリソースの定義と使い方を書いたが、これが「添付プロパティ」に使うためのリソースだと少々やり方が異なる。(ここも、UWPのローカライズ資料のままやってもうまくいかなかった部分。)
※添付プロパティは、例えばAutomationProperties.Name
などのこと。
リソース登録するときに、
リソース名.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name
という感じで、[using:名前空間名]
を入れて登録する。
使うときは、他のリソースと同じように、
x:Uid="リソース名"
で使う。
【注意】
AutomationProperties.Name にリソースを使う場合に、UWPのローカライズ資料だと、
Greeting.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name
と書けとあるが、実際は
MyButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name
でないといけない。(名前空間名が違う)
これはUWPでの「AutomationProperties.Name」と、WinUI3でのそれの出どころの違いだと思われる。地味にはまったので要注意。
(WinRTとWindows App SDKの違いなのか?)
その他
reswの内容を変更後は、リビルドしないと変更が動作に反映されない気がする。
これも地味にはまるので注意。
参考
WinUI3でローカライズする
package.appxmanifest に書く<Resource Language="x-generate"/>
の記載はココ。
https://docs.microsoft.com/ja-jp/windows/apps/winui/winui3/localize-winui3-app
UWPの文字列ローカライズのやり方 公式
UI とアプリ パッケージ マニフェスト内の文字列をローカライズする - UWP applications | Microsoft Docs
コードからリソースの文字列を取る方法のヒントになったissue
ResourceLoader のサンプル