web-dev-qa-db-ja.com

app.xamlでデフォルトのWPFウィンドウスタイルを設定する方法は?

App.xamlのWPF Windowsアプリケーションのすべてのウィンドウにデフォルトのスタイルを設定しようとしています。これまでのところ、私はこれをapp.xamlに持っています:

<Application.Resources>
    <ResourceDictionary>
        <Style x:Key="WindowStyle" TargetType="{x:Type Window}">
            <Setter Property="Background" Value="Blue" />
        </Style>
    </ResourceDictionary>
</Application.Resources>

このスタイルを使用するようにウィンドウに具体的に指示することで、アプリの実行時にウィンドウをこのスタイルで表示できます(VSデザイナーではありません)。

Style="{DynamicResource WindowStyle}

これは機能しますが、理想的ではありません。だからどうすればいいですか:

  1. すべてのウィンドウが自動的にスタイルを使用していますか(したがって、すべてのウィンドウでスタイルを指定する必要はありません)。
  2. VSデザイナーはスタイルを示していますか?

ありがとう!

63
NoizWaves

レイが言うことを追加するには:

スタイルの場合、キー/ IDを指定するか、TargetTypeを指定する必要があります。

FrameworkElementに明示的に指定されたスタイルがない場合、独自のタイプをキーとして使用して、常にStyleリソースを検索します
-WPFのプログラミング(Sells、Griffith)

TargetTypeを指定すると、そのタイプのすべてのインスタンスにスタイルが適用されます。しかし、派生型はそうではないようです... <Style TargetType="{x:Type Window}">は、すべてのカスタム派生/ウィンドウでは機能しません。 <Style TargetType="{x:Type local:MyWindow}">はMyWindowのみに適用されます。そのため、オプションは

  • スタイルを適用するeveryウィンドウのStyleプロパティとして指定するキー付きスタイルを使用します。デザイナーは、スタイル設定されたウィンドウを表示します。

    <Application.Resources>
        <Style x:Key="MyWindowStyle">
            <Setter Property="Control.Background" Value="PaleGreen"/>
            <Setter Property="Window.Title" Value="Styled Window"/>
        </Style>
    </Application.Resources> ...
    <Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}">  ...
  • または、Ctor/Initialization/Loadステージで一度Styleプロパティを設定する、カスタムBaseWindowクラス( 独自の癖 を持つ)から派生させることもできます。すべての派生には、スタイルが自動的に適用されます。 しかし、デザイナーはあなたのスタイルに気付かないでしょうあなたはあなたのアプリを実行してスタイルが適用されていることを確認する必要があります。 InitializeComponent(自動/デザイナー生成コード)を実行するため、XAMLは適用されますが、カスタムコードビハインドは適用されません。

したがって、明示的に指定されたスタイルは最も作業が少ないと思います。とにかくスタイルの側面を一元的に変更できます。

46
Gishu

これは数年後ですが、質問はまだここにあるので...

  1. プロジェクトにリソースディクショナリを作成します(プロジェクトを右クリック...)

    「Assets」という名前のプロジェクトの下に新しいフォルダーを作成し、それに「resourceDict.XAML」を配置します。

  2. ResourceDict.XAMLにコードを追加します。

    <Style x:Key="WindowStyle" Target Type="Window" >
         <Setter Property="Background" Value="Blue" />
    </Style>
    
  3. Project XAMLファイルの[ウィンドウ]に次を追加します。

    <Window.Resources>
        <ResourceDictionary>
            <!-- Believe it or not the next line fixes a bug MS acknowledges -->
            <Style TargetType="{x:Type Rectangle}" />
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Assets/resourceDict.XAML" />
            </ResourceDictionary.MergedDictionaries>
        <ResourceDictionary>
    </Window.Resources>
    

    次のWebサイトを参照してください: マージされた辞書を含むリソースディクショナリの参照に関するトラブル 最上位のディクショナリには3レベル(またはそれより深い)フラグが立てられないため、検索はスキップされます。回避策は、ルートディクショナリ内の何かにデフォルトスタイルを設定することです。そして、物事を確実に修正するようです。図を行く...

  4. そして最後に、ウィンドウの下で、おそらくタイトルの後、しかし最後のウィンドウ '>'の前に:

    Style="{DynamicResource windowStyle}"
    
  5. そして、スタイルを適用するすべてのプロジェクトに、手順3および4のコードを追加する必要があります。

  6. 単色ではなくグラデーションの背景を使用する場合は、resourceDict.XAMLに次のコードを追加します。

    <LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0"
            EndPoint="0,1" >
    <GradientStop Color= "AliceBlue" Offset="0" />
    <GradientStop Color= "Blue" Offset=".75" />
    </LinearGradientBrush>
    
  7. そして、背景色が読みやすいようにスタイルセッターを変更します。

    <Setter Property="Background" Value="{DynamicResource
            windowGradientBackground}" />
    

上記のように、各project.XAMLファイルで手順3と4を繰り返す必要がありますが、ソリューション全体で統一されたWindowsが得られます!また、同じプロセスを、ボタンなど、統一された外観にしたいコントロールにも適用できます。

遅くに来てくれる人にとっては、これが何年も前に考え出されたオリジナルのポスターに間違いないので、これが役立つことを願っています。

ポール

20
Paul1307

DynamicResourceを指定しているため、デザイナーは機能していません。これをStaticResourceに変更してください。すべてうまくいきます。

すべてのウィンドウに適用するには、スタイルからx:Keyを削除する必要があります。 TargetTypeを設定すると、x:KeyがTargetTypeにあるものに暗黙的に設定されます。しかし、私のテストでは、これは機能していませんので、調べています。

TargetTypeをx:Type TextBlockに設定すると、デザイナーは完全に動作します。異なる動作を示しているのはウィンドウのようです。

8
Ray Booysen

このコードをApp.xaml.csファイルに追加できます。

        FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
        {
            DefaultValue = Application.Current.FindResource(typeof(Window))
        });

この後、Window型に適用されるスタイルは、Windowから派生したすべての型にも適用されます

4
STiLeTT

これを数日間調査し、カスタムウィンドウクラスのコンストラクターで動作させました。

public class KWindow : Window
{
        public KWindow()
        {
            this.SetResourceReference(StyleProperty, typeof(KWindow));
        }

        static KWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow)));

        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // gets called finally
        }
}

それが誰かを助けることを願っています

3
KroaX

これらの問題の解決に苦労しています:すべてのウィンドウ派生型にカスタムスタイルを自動的に適用するにはどうすればよいですか?以下は私が思いついた解決策です

注:プロジェクトに固有の理由のために、ウィンドウタイプから派生したり、各ウィンドウにXAMLを挿入してスタイルの更新などを強制する必要は本当にありませんでした(製品の消費者は汎用の再利用可能なスタイルライブラリを使用して独自のライブラリを作成しますレイアウト/ウィンドウなど)私は本当にやる気私がどんな副作用でも喜んで生きることができる解決策を見つけ出す

インスタンス化されたすべてのウィンドウを反復処理し、ウィンドウタイプに定義した新しいカスタムスタイルを使用するよう強制する必要があります。これは、既に起動しているウィンドウに対してはうまく機能しますが、ウィンドウまたは子ウィンドウがインスタンス化されると、そのベースタイプに対して宣言されている新しい/カスタムタイプを使用することを知りません。バニラウィンドウタイプ。だから、私が思いついたのは、MainWindowがChildWindowへのフォーカスを失ったとき(子ウィンドウが作成されたときのIOW)にLostKeyBoardFocusを使用してから、このFixupWindowDerivedTypes()を呼び出すことでした。

何らかの種類のウィンドウ派生型がインスタンス化されたときに「検出」するためのより良いソリューションがあり、したがって、素晴らしいFixupWindowDerivedTypes()を呼び出した場合。この領域でもWM_WINDOWPOSCHANGINGを処理するのに役立つ何かがあるかもしれません。

したがって、このソリューションは、一見エレガントではありませんが、ウィンドウに関連するコードやXAMLに触れることなく作業を完了できます。

   public static void FixupWindowDerivedTypes()
    {
        foreach (Window window in Application.Current.Windows)
        {
           //May look strange but kindly inform each of your window derived types to actually use the default style for the window type

                    window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window));
                }
            }
        }
    }


//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection.
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html

//Helper class to retrieve a protected property so we can set it
internal class DefaultStyleKeyRetriever : Control
{
    /// <summary>
    /// This method retrieves the default style key of a control.
    /// </summary>
    /// <param name="control">The control to retrieve the default style key 
    /// from.</param>
    /// <returns>The default style key of the control.</returns>
    public static object GetDefaultStyleKey(Control control)
    {
        return control.GetValue(Control.DefaultStyleKeyProperty);
    }
}
1
Arnie

Gishの答えを考えて、もう1つの回避策を見つけました。しかし、それは少し奇妙かもしれません。 MVVMパターンを使用する場合、ウィンドウのコードビハインドとXAMLファイルのx:Classマークアップを削除できます。そのため、ウィンドウまたはカスタムウィンドウのインスタンスを取得しますが、「ウィンドウ」クラスから派生し、パーシャルとしてマークされた「メインウィンドウ」クラスのインスタンスは取得しません。 VSのようなウィンドウを作成しているため、ウィンドウクラスを継承し、機能を拡張する必要がありました。その場合、継承なしで分離コードを作成できるように、新しいウィンドウクラスをパーシャルとして作成することができます。

0
Crossman