WinUI3アプリから、別のDLLに置いてあるResourceDictionaryを使う

もくじ
https://tera1707.com/entry/2022/02/06/144447#WinUI3

やりたいこと

WinUI3アプリから、同じくWinUI3のライブラリのプロジェクトにおいてあるリソースディクショナリの中のリソースを参照できるようにして、リソースを複数プロジェクトで共用したい。

また、WPFのときの、MergeDictionaryのところに<ResourceDictionary Source="pack://application:,,,/ResourceTestLib;component/Styles/_Thickness.xaml"/> てな感じで書くやり方だと、うまくいかなかった。

WInUI3でお作法が変わったのかも?調べたい。

前提

  • Windows10 Home 21H1 19043.1706
  • VisualStudio2022 Community 17.1.4
  • WinUI3.0
  • Windows App SDK 1.0
  • 2022年5月の時点の調査

やり方

やはり、WPFとはやり方が異なる様子。

WPFのときは、Pack URIsというお作法を使っていたのが、 WInUI3(というより、パッケージしたアプリ?未検証)では、URI schemesというお作法に変わった様子。

こういう感じ。

<ResourceDictionary Source="ms-appx:///プロジェクト名/サブディレクトリ名/リソースディクショナリの名前.xaml" />

サンプルコード

構成

実験では、こういう構成にする。

プロジェクト名 内容
ResourceDicFromOtherDll メインのWinUI3アプリ。
RcDicLib WinUI3アプリから見るリソースディクショナリを持つDLL。
ResourceDicFromOtherDll (Package) WinUI3アプリをパッケージするためのパッケージプロジェクト。(とくに今回は触らない)

RcDicLibプロジェクトの中にあるResourceDictionary1.xamlSubDirectory\ResourceDictionary2.xamlが、今回つくるリソースディクショナリ。

コード

要点、初期状態から変更した部分だけ抜粋。

ResourceDicFromOtherDll(ディクショナリを使う側のWinUI3アプリ)

App.xaml
ResourceDictionary1と2をマージディクショナリする部分を追加。

ここが今回の一番の要点。

<Application
    x:Class="ResourceDicFromOtherDll.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ResourceDicFromOtherDll">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!-- Other merged dictionaries here -->
                <ResourceDictionary Source="ms-appx:///RcDicLib/ResourceDictionary1.xaml" />
                <ResourceDictionary Source="ms-appx:///RcDicLib/SubDirectory/ResourceDictionary2.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <!-- Other app resources here -->
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml
リソースを実際に使う部分。今回はボタンの背景色と文字色に定義したブラシを使用。

<Window
    x:Class="ResourceDicFromOtherDll.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ResourceDicFromOtherDll"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Background="{StaticResource TestBrush1}"
                Foreground="{StaticResource TestBrush2}">
            リソースディクショナリ1より
        </Button>
        
        <Button Background="{StaticResource TestBrush3}"
                Foreground="{StaticResource TestBrush4}">
            リソースディクショナリ2より
        </Button>
    </StackPanel>
</Window>

RcDicLib(ディクショナリを持つDLL)

ResourceDictionary1.xaml
プロジェクトの直下に置いてある。緑と赤のブラシを定義。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RcDicLib">

    <SolidColorBrush x:Key="TestBrush1" Color="#FFFF0000"/>
    <SolidColorBrush x:Key="TestBrush2" Color="#FF00FF00"/>

</ResourceDictionary>

SubDirectory\ResourceDictionary2.xaml
サブディレクトリの中に置いてある。黄色と水色のブラシを定義。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RcDicLib.SubDirectory">

    <SolidColorBrush x:Key="TestBrush3" Color="#FFFFFF00"/>
    <SolidColorBrush x:Key="TestBrush4" Color="#FF00FFFF"/>
    
</ResourceDictionary>

実行した結果

こんな感じで、リソースディクショナリ内のブラシが適用されている。

追記

パッケージしてないWinUI3アプリでも、同じ方法が使えそう。

WinUI3のexeをパッケージせずに実行する方法で試した、 <WindowsPackageType>None</WindowsPackageType>を追加してパッケージしないWinUI3で動かしてみても、同じ今回のms-appxのやり方でリソースディクショナリを問題なく使うことができた。

参考

URI schemes MS公式ドキュメント。

https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes

WinUI XAML: Using a ResourceDictionary from another project

https://stackoverflow.com/questions/70215170/winui-xaml-using-a-resourcedictionary-from-another-project

WPFのときの書き方。WinUI3のパッケージしたプロジェクトには使えない。

https://docs.microsoft.com/en-us/dotnet/desktop/wpf/app-development/pack-uris-in-wpf?view=netframeworkdesktop-4.8

WPFのときに参考にした記事

https://qiita.com/NumAniCloud/items/3d64199aee8876d53f67

参考書

WinUI3

WinUI3でアプリを作ろうと思ったときのとっかかりによかった。 msdocsに書いてある情報を、体系的に、順番に読みたいな、というときによいかも。(ただし英語)
この本で分からなかった、かゆいところに手が届かなかった部分を私は記事にしてる感じ。

C#①

表紙に書いてある通り、教科書として最適。 これからC#を勉強したいけど、ネットだけで勉強するのは効率が悪いから体系的に学べる本が欲しいときや、 ちょっとC#を勉強してコード書けるようになったけど、もう少し広く深く知りたいなというときによいと思う。
私は仕事で触れるコードを軸に、基本ネットで断片的にC#を学んだので、その知識の隙間を埋めて枝葉を広げるためにとても分かりやすかった。

C#②

C#の文法的に色々できるのは分かったが、いざ実装するときに、わかったことを使ってどう実装すればいいのか?と悩んだときに指針になりそうな本。
「プロパティ等の名前の付け方、どうすればいい?」「情報をクラス外部に見せるときに、プロパティにすべき?メソッドにすべき?」「異常だと判定したいとき、どんなときにどんな例外をスローすべき?」などなど、勉強になる部分が山ほどあった。
私のように「コードは書くけどこれであってるのか自信がない、レビューで指摘されるのが嫌だ、実装時の(心の)よりどころが欲しい」という人に最適。