0

ResourceDictionaries からのリソースの解決に問題があります。

かなり大きな ResourceDictionary を、サブフォルダーに編成された個々の辞書ファイルにリファクタリングすることにしました。

Resources の下に ResourceLibrary.xaml があります。

<ResourceDictionary x:Class="MyProject.Resources.ResourceLibrary"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <ResourceDictionary.MergedDictionaries>
     <!-- Colours -->
     <ResourceDictionary Source="Colors/ConnectedCellColor.xaml" />
     <!-- Brushes -->
     <ResourceDictionary Source="Brushes/ConnectorCellBrush.xaml" />
     <!-- Control Templates -->
     <ResourceDictionary Source="ControlTemplates/ConnectorCellTemplate.xaml" />
     <!-- Base Styles -->
     <ResourceDictionary Source="BaseStyles/ConnectorBaseStyle.xaml" />
   </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

クラスが存在するのには理由があります。コード ビハインドで [Export(typeof (ResourceDictionary))] を追加して、MEF がそれを見つけられるようにします。

ビューがあります:(簡略化)

<UserControl x:Class="MyProject.ConnectorCellView"
         Style="{StaticResource ConnectorBaseStyle}"
</UserControl>

ConnectorBaseStyle:

<ResourceDictionary>
   <Style x:Key="ConnectorBaseStyle" TargetType="UserControl">
      <Setter Property="Template" Value="{StaticResource ConnectorCellTemplate}" />
   </Style>
</ResourceDictionary>

テンプレートには、ブラシと色を取得しようとする StaticResources があります。

これらの StaticResources はすべて解決されなくなります。

順序の問題かもしれないと思いましたが、これらのリソースはメイン プログラムのプラグインに含まれているため、MEF と ImportMany を使用して、エクスポートされたすべての ResourceDictionaries を取得し、Caliburn.Micro ブートストラップで次のようにします。

  public void OnImportsSatisfied()
  {
     foreach (ResourceDictionary resourceDictionary in ResourceDictionaries)
     {
        Application.Resources.MergedDictionaries.Add(resourceDictionary);
     }
  }

(どこかで見つけた巧妙なトリック)

実際にプログラムを実行できます。そのビューが作成されると、スタイルを設定しようとすると例外がスローされます。

System.InvalidCastException
タイプ 'MS.Internal.NamedObject' のオブジェクトをタイプ System.Windows.FrameworkTemplate' にキャストできません。

これに関連して私が見つけた唯一の情報は、リソースが定義されている順序に関係していますが、ResourceLibrary にある順序から、それは機能するはずです。

例外がスローされると、Application.Current.Resources.MergedDictionaries を調べて、リソースを確認できます。

ResourceLibrary で Source を指定するさまざまな方法を試しました

<ResourceDictionary Source="/MyProject;component/Resources/BaseStyles/ConnectorBaseStyle.xaml" />

など、それらを見つけることには影響しません。これらのリソースは、プラグイン コードによってのみ使用されます。

機能しているように見えた唯一のことは、すべての StaticResources を DynamicResources に変更することでした

それが順序の問題である場合、なぜそれらがすべて同じファイルにあるときに Static が機能するのでしょうか?

私のスタイルのいくつかは BasedOn を使用していましたが、DynamicResource では機能しません。

なぜこれが起こっているのか、そしてそれを機能させる方法を理解するのを手伝ってもらえますか?

4

1 に答える 1

1

これは順序の問題ですが、マージの順序の問題ではありません。ロードの順序の問題です。ResourceLibrary ディクショナリが読み込まれると、基本的に次のようになります。

  1. ConnectedCellColor はインスタンス化します
  2. ConnectedCellColor が ResourceLibrary にロードされます
  3. ConnectorCellBrush のインスタンス化
  4. ConnectorCellBrush が ResourceLibrary に読み込まれます
  5. ConnectorCellTemplate はインスタンス化します
  6. ConnectorCellTemplate が ResourceLibrary に読み込まれます
  7. ConnectorBaseStyle はインスタンス化します
  8. ConnectorBaseStyle が ResourceLibrary にロードされます

ここでの問題は、以前は 1 つのファイルで 1 つのインスタンス化ステップしかなかったのに、今ではそれが複数のステップに分割され、それぞれが独立して発生することです。ConnectorBaseStyle がインスタンス化されている場合、ConnectorCellTemplate はロードされていますが、この時点では ResourceLibrary の内容は ConnectorBaseStyle に認識されていません。DynamicResourceこれらの参照はステップ 8 で解決できますが、ステップ 7 ですぐに解決する必要があるため、これは問題ではありませんStaticResource

最も簡単な修正は、可能Dynamicな限り使用することです。を必要とする場所Static( などBasedOn) では、たとえば ConnectorCellTemplate を ConnectorBaseStyle にマージするか、必要なすべてのものを App.xaml にマージして、インスタンス化中にリソースが使用できることを保証する必要があります。これにより、より多くのファイルを取得して複数の場所にマージすると、物事が複雑になり、管理が難しくなる可能性がありますが、少なくともリソース システムは重複を認識するのに十分なほどスマートであるため、上記の場合でも、ConnectorCellTemplate の単一のインスタンスしか取得できません。 2ヶ所で合流中。

于 2013-02-04T17:18:23.907 に答える