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