2

これが役立ついくつかの異なるアプリケーションがありますが、具体的な例として、WinForms アプリケーションがあるとします。

このアプリケーションは、ElementHostオブジェクト内で WPF コントロールを利用します。ここで、すべての WPF ボタン ( System.Windows.Controls.Button)に対して暗黙的なスタイルを定義ElementHostして、リソース ディクショナリにマージする必要がなくButton、スタイルを明示的に指定する必要がないようにしたいと考えています。

上記のスタイルをどこで定義しますか?

Themes\Generic.xamlプロジェクトルートにリソースディクショナリを作成して指定してみました

[assembly: ThemeInfo(
    ResourceDictionaryLocation.None,
    ResourceDictionaryLocation.SourceAssembly )]

AssemblyInfo.cs。これは機能しませんでした。そのスタイルは、同じアセンブリで定義されたカスタム コントロールに対してのみ存在するという印象を受けました。as はButton外部アセンブリで定義されています。

例では、暗黙的なスタイル コードを に配置し<Application.Resources>ます。ただし、そのノードは with-inApp.xamlであり、これは (プロジェクトが WPF アプリケーションとして開始されていない) 存在しません。を追加することは可能ですか、またはそれらが認識されるようApp.xamlに配置する他の場所はありますか?<Application.Resources>

4

2 に答える 2

2

Dr WPF にはいくつかの提案があります:
http://drwpf.com/blog/2007/10/05/managing-application-resources-when-wpf-is-hosted/

以下にいくつかの関連部分を引用します。


アプリケーション インスタンスを作成し、コードでリソースを追加する
以下は、アプリケーション オブジェクトが存在しない場合にそれを作成し、いくつかのリソースをロードする非常に単純な関数です。

public static void EnsureApplicationResources()
{
    if (Application.Current == null)
    {
        // create the Application object
        new Application();

        // merge in your application resources
        Application.Current.Resources.MergedDictionaries.Add(
            Application.LoadComponent(
               new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
               UriKind.Relative)) as ResourceDictionary);
    }
}

ここで必要なのは、アプリケーション レベルのリソースへの静的リソース参照を含む XAML ファイルを解析する前に、この関数を呼び出すことを確認することだけです。これを行うには、マークアップ ベースのクラスのコンストラクターで、 への呼び出しの前に上記の関数への呼び出しを追加するだけですInitializeComponent()

public Page1()
{
    EnsureApplicationResources();
    InitializeComponent();
}

XAML でアプリケーション クラスを定義し、その場で作成する
まず、MSBuild でアプリケーション クラスのアプリケーション エントリ ポイントを生成しないようにします。App.xamlそのため、ファイルをプロジェクト ファイル内の要素として宣言する代わりに、ApplicationDefinition要素として宣言する必要がありますPage

<Page Include="App.xaml" />
<Compile Include="App.xaml.cs">
  <DependentUpon>App.xaml</DependentUpon>
  <SubType>Code</SubType>
</Compile>

App.xaml次に、マークアップが解析されていることを確認する必要があります。通常、これはエントリ ポイント関数の一部として行われます (先ほど削除しました)。Application代わりに、クラスのコンストラクターを定義してInitializeComponent直接呼び出すことができます。

public App()
{
    InitializeComponent();
}

これで、すべてのリソースとマージされた辞書を宣言できApp.xaml、Application インスタンスをロードする静的関数は次のように単純になります。

public static void EnsureApplicationResources()
{
    if (Application.Current == null)
    {
        // create the Application object
        new App();
    }
}

コードでリソース ディクショナリのコレクションを管理し、要素レベルでマージするこのシナリオでは、オブジェクトをまったく
活用しません。Application代わりに、実行時にそれぞれを動的にロードResourceDictionaryし、必要に応じてページ、ウィンドウ、または特定の要素に選択的にマージします。

public static class SharedResources
{
    public static readonly DependencyProperty MergedDictionariesProperty =
        DependencyProperty.RegisterAttached("MergedDictionaries",
            typeof(string), typeof(SharedResources),
            new FrameworkPropertyMetadata((string)null,
                new PropertyChangedCallback(OnMergedDictionariesChanged)));

    public static string GetMergedDictionaries(DependencyObject d)
    {
        return (string)d.GetValue(MergedDictionariesProperty);
    }

    public static void SetMergedDictionaries(DependencyObject d, string value)
    {
        d.SetValue(MergedDictionariesProperty, value);
    }

    private static void OnMergedDictionariesChanged(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        if (!string.IsNullOrEmpty(e.NewValue as string))
        {
            foreach (string dictionaryName in (e.NewValue as string).Split(';'))
            {
                ResourceDictionary dictionary = GetResourceDictionary(dictionaryName);
                if (dictionary != null)
                {
                    if (d is FrameworkElement)
                    {
                        (d as FrameworkElement).Resources
                            .MergedDictionaries.Add(dictionary);
                    }
                    else if (d is FrameworkContentElement)
                    {
                        (d as FrameworkContentElement).Resources
                            .MergedDictionaries.Add(dictionary);
                    }
                }
            }
        }
    }

    private static ResourceDictionary GetResourceDictionary(string dictionaryName)
    {
        ResourceDictionary result = null;
        if (_sharedDictionaries.ContainsKey(dictionaryName))
        {
            result = _sharedDictionaries[dictionaryName].Target;
        }
        if (result == null)
        {
            string assemblyName = System.IO.Path.GetFileNameWithoutExtension(
                Assembly.GetExecutingAssembly().ManifestModule.Name);
            result = Application.LoadComponent(new Uri(assemblyName
                + ";component/Resources/" + dictionaryName + ".xaml",
                UriKind.Relative)) as ResourceDictionary;
            _sharedDictionaries[dictionaryName] = new WeakReference(result);
        }
        return result;
    }

    private static Dictionary<string, WeakReference> _sharedDictionaries
        = new Dictionary<string, WeakReference>();
}

これにより、次のようにするだけで、共有リソース ディクショナリを任意のフレームワーク要素の Resources コレクションにマージできます。

<Grid dw:SharedResources.MergedDictionaries="ApplicationBrushes;ButtonStyles">
于 2012-12-19T13:25:23.273 に答える