S.F. Page

Programming,Music,etc...

StandardStyles.xamlが反映されない

やっぱりおかしい

基本ページを問題なく追加できたように見えたが、何かおかしい。タイトルの文字サイズが異様に小さいのである。

よく見ると追加しているページでエラーが発生している。

エラー	1	リソース "LayoutRootStyle" を解決できません。
エラー	2	リソース "Standard80ItemTemplate" を解決できません。
エラー	3	リソース "PageHeaderTextStyle" を解決できません。
エラー	4	リソース "PortraitBackButtonStyle" を解決できません。
エラー	5	リソース "SnappedBackButtonStyle" を解決できません。
エラー	6	リソース "SnappedPageHeaderTextStyle" を解決できません。

StandardStyles.xamlは追加しているし、エラーが発生しているスタイルはきちんと定義されている。これはなぜなのだろうか。やっぱり昨日プロジェクトを追加したときに何か発生したのだろうか。エラーの感じからすると参照できていないように思える。プロジェクトに追加するだけでは参照されないのだろうか。

App.XAMLでマージしないといけなかった

リソースのマージとかってどこでやるのかなと考えると、App.xamlが怪しそうである。新たにプロジェクトを作りApp.XAMLを見るとやっぱりそうだった。

<Application
    x:Class="App1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    プラットフォームの外観の共通の要素を定義するスタイル
                    Visual Studio プロジェクトおよびアイテム テンプレートで必要です
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>
    </Application.Resources>
</Application>

ResourceDictionary.MergedDictionariesというのがあり、ここにStandardStyles.xamlを追加してやればよいらしい。 おそらくこの作業は「基本ページの追加」技で追加されるはずのものが、私のヘンテコプロジェクトのせいで途中でエラーになってのかもしれない。 <ResourceDictionary>全体をコピーし、<Application.Resources>内の最後にペーストしてみるとまたエラー発生。

エラー	1	プロパティ "Resources" は 1 回しか設定できません。
エラー	2	Key属性は "IDictionary" 内の要素でのみ使用できます。
エラー	3	指定された値を割り当てることができません。次の型の値を指定してください: "ResourceDictionary"

これはどうしたものか。。

解決策

結局どうしたかというと、

  1. 新しい項目として、リソースディクショナリ(.xaml)ファイル(SFGameStyles.xaml)を追加
  2. そこにもともとApp.xamlの<Application.Resources>内部の内容をカット&ペースト
  3. 下記の内容をApp.xamlに追加

           <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
    
                    <!-- 
                        プラットフォームの外観の共通の要素を定義するスタイル
                        Visual Studio プロジェクトおよびアイテム テンプレートで必要です
                     -->
                    <ResourceDictionary Source="Common/StandardStyles.xaml"/>
                    <ResourceDictionary Source="./SFGameStyles.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
    

    <ResourceDictionaryの2つ目に追加するのがポイントである。

こうすることで問題を解決することができた。

なぜこうなるのかの分析

結局リソース・ディクショナリのマージ設定記述時に出るエラーは「 <Application.Resources>直下に定義できるエレメントは1個でないといけない。」といけない風に読める。<ResourceDictionary>の定義が一つもない場合は<Application.Resources>の直下にリソース定義を書くと暗黙の<ResourceDictionary>で囲まれるような気もする。

私自身XAMLリソースの仕様についてよくわかっていないので少し探ってみる。

Application.Resources Propertyを見るとその型はResourceDictionaryである。つまりこのプロパティにセットするのはResourceDictionaryでなければならない。よってApplication.Resources直下にリソース定義を書くと暗黙のResourceDictionaryが定義されるようである。ならばResourceDictionary.MergedDictionariesをリソース定義中にふくめても大丈夫そうだがこれはエラーとなってしまう。試しに明示的にリソース定義をResourceDictionaryで囲み、その中にResourceDictionary.MergedDictionaries定義を入れてやると問題なく動作する。エラーも発生しない。

ResourceDictionaryのリファレンスを読むと以下の内容が書いてあった。

ResourceDictionary の XAML の暗黙的なコレクション構文には、ResourceDictionary の要素は含まれていません。これは、XAML の暗黙的なコレクション構文の 1 つの例で、コレクション要素を表すタグは省略可能です。コレクションに項目として追加される要素は、基になる型が辞書またはマップの Add メソッドをサポートしているプロパティのプロパティ要素の子要素として指定されます。

要するにそういうことだった。わかったことは、

  • Application.Resourcesプロパティにリソース定義を書くと、暗黙のResourceDictionary定義がなされる。
  • 暗黙のResourceDictionary定義中ではResourceDictionary.MergedDictionaries定義を入れることはできず、エラーとなる
  • Application.Resources中にResourceDictionary.MergedDictionaries定義とリソース定義を混在させたい場合は、明示的にResourceDictionary定義を入れる。

である。腑に落ちたような、落ちないような。。