5

WinForms コンテナーで WPF UserControl をホストしています。ここで、UserControl のテーマ/スキンを設定できるようにしたいと考えています。これを行うために、「スキン」を定義するリソース ディクショナリをいくつか用意しました。アプリが起動したら、「新しい System.Windows.Application()」を作成して、Application.Current が存在するようにします。テーマを変更するには、実行時に古いスキンを削除し、新しいスキンをアプリケーション レベルのリソース ディクショナリにマージします。ただし、これにより、UserControl で動的に参照されるリソースは変更されません。これをストレートな WPF アプリケーションで試してみたところ、問題なく動作しました。私は何かを見逃していますか、それともこれを行うことはまったく不可能ですか? ちなみに、UserControl を初期化する前にアプリケーション リソースにスキンを追加すると機能しますが、その後スキンを変更することはできません。

これを最も基本的な方法でレポするには:

新しい WinForms アプリケーションを作成します。アプリに WPF UserControl を追加します。これはとても簡単です:

<UserControl ...>
   <Grid>
      <Button
         Background="{DynamicResource ButtonBG}"/>
   </Grid>
</UserControl>

それぞれの色のキー ButtonBG を持つ SolidColorBrush を持つ 2 つの ResourceDictionaries、White.xaml と Black.xaml (または何でも) を作成します。Form1.cs で、2 つのボタンと ElementHost を追加します。ElementHost の子を、作成したばかりの UserControl のインスタンスに設定します。スキンを交換するイベントにボタンを接続します。

private void White_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));
}

private void Black_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\Black.xaml", UriKind.Relative)));
}

Program.cs で、Application.Current が存在することを確認し、初期スキンを設定します。

[STAThread]
static void Main()
{
   new System.Windows.Application();

   Application.Current.Resources.MergedDictionaries[0] =
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));

   ...
}

ここで、白のボタンをクリックすると、UserControl のボタンが白に変わり、黒のボタンをクリックするとボタンが黒に変わることが期待されます。ただし、これは起こりません。

誰かが理由を知っていますか?解決策はありますか?

編集:アイデア: おそらく、テーマが変更されたときに DynamicResources の再評価を強制する方法があれば、それはうまくいくでしょう。

ありがとう、ダスティ

4

3 に答える 3

6

これは、WPFフレームワークでは見落とされている問題かもしれないと思います。

リフレクターを介して私が知ることができることから、Applicationリソースディクショナリが壊滅的に変更された場合(スキンの追加、削除、置換などの幅広い影響を与える可能性が高い変更)、のすべてをループするコードがあるようですWindows。アプリケーションを実行し、それらを再評価するように強制しますDynamicResources。ただし、sのようなWPFのトップレベルと見なす他の要素はElementHost、同じ扱いを受けません。これは私が経験している行動につながります。

この問題の回避策は、すべてのを手動で個別に調べて、スキンファイルElementHostを追加、削除、または置換することです。ResourceDictionaryそれは完璧ではありませんが、それは仕事を成し遂げます。

于 2009-05-01T18:40:24.537 に答える
-1

もう 1 つの回避策は、ダミー ウィンドウを作成し、要素ホストのコンテンツをコンテンツとして指定することです。アプリケーションを調べて、リソース辞書の変更をどのように処理するかを確認すると、ウィンドウにのみ通知することがわかります..

注意すべき唯一のことは、ウィンドウを表示しない (-> 例外) ことと、要素ホストを破棄するときにウィンドウを閉じて、アプリケーションが適切にシャットダウンできるようにすることです。

于 2014-07-24T07:44:23.147 に答える