2

次の要件があります。

  1. 私のWPFアプリケーションは、いくつかのモジュール(アセンブリ)で構成されており、そのうちのいくつかはUI関連です。

  2. 特定のコントロールの共通のスタイルセット(カスタムのデフォルトボタンスタイルなど)を含む単一のアセンブリを作成したいのですが、その1つのアセンブリを含めるだけで、指定しなくても、他のすべてのUI関連のアセンブリに自動的に適用されます。明示的なリソースキー。

  3. 私はすべての種類のコントロールにスタイルを提供しているわけではないので、カスタムスタイルがない場合は、デフォルトのAeroテーマ(コンテンツテンプレートなどを含む)を維持する必要があります。

  4. 独自の拡張Buttonクラスなどを作成したくありませ

  5. これを、最終的なアプリと他のUI関連モジュールの両方で、デザイン時にVisualStudioでも機能させたいと思います。

スタイルはアセンブリ内で定義されているため、App.xamlをそこに置くことはできません。したがって、Generic.xamlからそれらを含める必要があると思います。Generic.xamlは、標準(Aero)テーマで定義されたスタイルがない場合にのみフォールバックとして機能するため、WPFはGeneric.xamlの私のスタイルを無視します。

次のステップは、おそらく私自身のテーマを作成することです(それはどういうわけかデフォルトのAeroスタイルをマージします)。しかし、Aeroなどではなく、アプリとモジュールの両方でそのテーマを使用するようにVSに指示するにはどうすればよいですか?カスタムスタイルのデザイン時のサポートが必要なため、これを宣言的に行う必要があると思います。

4

3 に答える 3

5

スタイル アセンブリへの参照を追加するだけでは不十分です。WPF にリソースをマージさせるには、何かを行う必要があります。ただし、C# の 1 行 (または XAML の数行) をアプリケーション アセンブリに追加するだけでよい方法でこれを行うことができます。

最も簡単な解決策は、おそらく、共有スタイル アセンブリに厳密に型指定されたものを作成し、起動時にResourceDictionaryアプリ レベルに追加することです。ResourceDictionary

たとえば、CustomStyles.xaml共有スタイル アセンブリに を作成し、すべてのスタイル リソースをそのファイルに (直接または 経由でMergedDictionaries) 取り込みます。Build Action が「Page」に設定されていることを確認し、次のように要素にx:Classディレクティブを追加します。ResourceDictionary

<ResourceDictionary x:Class="YourNamespace.CustomStyles"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <!-- Your styles declared or imported here -->
</ResourceDictionary>

組み込みまたはサードパーティのコントロール スタイルを置き換えることを意図したスタイルの場合、スタイルを暗黙的に宣言できます。つまり、x:Key完全にオフのままにするか、コントロールのタイプをキーとして使用できます (例: x:Key="{x:Type ComboBox}".

ディレクティブを追加するだけでは、Visual Studioが XAML コンテンツを実際にロードx:Classするコンストラクターを生成するにはおそらく十分ではないため、ファイルを手動で追加し、それを呼び出すコンストラクターを与える必要があります(VS はこれを生成する必要があります)。CustomStyles()CustomStyles.xaml.csInitializeComponent()

namespace YourNamespace
{
    partial class CustomStyles
    {
        public CustomStyles()
        {
            InitializeComponent();
        }
    }
}

アプリケーションでは、このディクショナリをディクショナリにマージする必要がありますApplication.ResourcesApp.xaml必要に応じて、ファイルからこれを行うことができます。

<Application x:Class="YourNamespace.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:cs="clr-namespace:YourNamespace;assembly=YourCustomStylesAssembly">
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <cs:CustomStyles />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

...または、C# 側で実行できます。

public partial class App
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        this.Resources.MergedDictionaries.Add(new CustomStyles());
    }
}

ここで注意が必要なのは、これらのスタイルを XAML デザイナーで機能させることです。頭に浮かぶ解決策の 1 つは、すべてのビューで設定でき、デザイナーで実行している場合にのみ適用されるカスタム添付プロパティを追加することです。

partial class CustomStyles
{
    public static readonly DependencyProperty EnableDesignTimeStylesProperty =
        DependencyProperty.RegisterAttached(
            "EnableDesignTimeStyles",
            typeof(bool),
            typeof(CustomStyles),
            new PropertyMetadata(
                default(bool),
                OnEnableDesignTimeStylesChanged));

    private static CustomStyles DesignTimeResources;

    private static void OnEnableDesignTimeStylesChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        if (!DesignerProperties.GetIsInDesignMode(d))
            return;

        var element = d as FrameworkElement;
        if (element == null)
            return;

        if (DesignTimeResources == null)
            DesignTimeResources = new CustomStyles();

        if ((bool)e.NewValue)
            element.Resources.MergedDictionaries.Add(DesignTimeResources);
        else
            element.Resources.MergedDictionaries.Remove(DesignTimeResources);
    }

    public static void SetEnableDesignTimeStyles(
        DependencyObject element,
        bool value)
    {
        element.SetValue(EnableDesignTimeStylesProperty, value);
    }

    public static bool GetEnableDesignTimeStyles(DependencyObject element)
    {
        return (bool)element.GetValue(EnableDesignTimeStylesProperty);
    }
}

次に、ビューでCustomStyles.EnableDesignTimeStyles="True"、デザイナーにスタイル リソースを強制的にマージするように設定します。実行時にDesignerProperties.GetIsInDesignMode(d)は と評価されfalse、最終的にすべてのビューにスタイルの新しいコピーをロードすることはありません。アプリレベルのリソースから継承するだけです。

于 2014-10-17T15:29:32.687 に答える
0

私が取り組んでいた PRISM アプリケーションでも、これらと同じ問題に苦しんでいました。スタック オーバー フローの調査を行った後、設計時にリソースを機能させるための最も簡単な答えは、UI ベースの各モジュールに App.Xaml を追加することであることに驚きました。アプリケーションが遵守されると、それらはすべて無視されます。しかし、設計時には、それらは設計者によって使用されます。上記の残りのアドバイスに従うと、すべてのスタイルを含むリソース ライブラリを指すマージされたリソース ディクショナリを持つ App.Xaml が得られます。

これは、デザイン時にスタイルを取得するために私が見つけた最も簡単な方法です。

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

<Application.Resources>

    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary  Source= "pack://application:,,,/Infrastructure;component/ResourceDictionaries/ResourceLibrary.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="{x:Type Rectangle}"/>
    </ResourceDictionary>

</Application.Resources>

先人の知識を蓄積して、PRISM のリソース ディクショナリに関する私の経験を詳述 したブログ投稿をまとめました。

于 2014-10-20T04:55:14.003 に答える
0

それらをすべて自動的に適用する方法がわかりません。実際、「自動、デザイナーサポート、および複数のアセンブリ」の組み合わせは不可能だと思います。ただし、各コントロールにヘッダー参照を追加するのは簡単です。

ステップ 1: すべてのスタイルを、他のすべてのプロジェクトによって参照される「スタイル」プロジェクトのディクショナリにマージまたは追加します。

手順 2: コントロールおよびその他のリソース ディクショナリ XAML ファイルのそれぞれに、このディクショナリへの参照を含めます。次のようにスムーズに表示されます。

<ResourceDictionary.MergedDictionaries>
   <SharedResourceDictionary Source="pack://application:,,,/My.Ui.Resources;component/Themes/ColorSkins/LightTheme.xaml" />
...

インスタンスを複製しないために SharedResourceDictionary を使用することに注意してください。http://blogs.msdn.com/b/wpfsdk/archive/2007/06/08/defining-and-using-shared-resources-in-a-custom-control-library.aspxを参照してください 。

および SharedResourceDictionary: Blend でリソースを編集する

すべてのコントロールが同じベースから継承されている場合、それらをプログラムでインクルードする独自のベース クラスを作成すると便利な場合があります。

于 2014-10-17T15:42:22.453 に答える