it-swarm.com.de

Wie setze ich den Standard-WPF-Fensterstil in app.xaml?

Ich versuche, den Standardstil für jedes Fenster in meiner WPF-Windows-Anwendung in meiner app.xaml festzulegen. Bisher habe ich dies in app.xaml:

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

Ich kann erreichen, dass das Fenster mit diesem Stil angezeigt wird, wenn die App ausgeführt wird (dies ist jedoch kein VS-Designer), indem ich dem Fenster anweise, diesen Stil zu verwenden:

Style="{DynamicResource WindowStyle}

Das funktioniert, ist aber nicht ideal. Wie mache ich:

  1. Haben alle Fenster automatisch den Stil verwendet (damit ich ihn nicht in jedem Fenster angeben muss)?
  2. Haben VS Designer den Stil zeigen?

Vielen Dank!

63
NoizWaves

So ergänzen Sie die Aussagen von Ray:

Für die Stile müssen Sie entweder einen Schlüssel/eine ID angeben oder einen Zieltyp angeben.

Wenn ein FrameworkElement keinen explizit angegebenen Style hat, sucht es immer nach einer Style-Ressource, wobei sein eigener Typ als Schlüssel verwendet wird
- Programmierung von WPF (Sells, Griffith)

Wenn Sie einen TargetType angeben, wird auf alle Instanzen dieses Typs der Stil angewendet. Abgeleitete Typen werden jedoch nicht ... es scheint. <Style TargetType="{x:Type Window}"> funktioniert nicht für alle Ihre benutzerdefinierten Ableitungen/Fenster. <Style TargetType="{x:Type local:MyWindow}"> gilt nur für MyWindow. Die Optionen sind also

  • Verwenden Sie einen Keyed Style, den Sie als Style-Eigenschaft für jedes Fensters angeben, auf das Sie den Style anwenden möchten. Der Designer zeigt das gestaltete Fenster an.

.

    <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}">  ...
  • Sie können auch von einer benutzerdefinierten BaseWindow-Klasse (mit eigenen Eigenheiten ) ableiten, in der Sie die Style-Eigenschaft während der Ctor/Initialization/Load-Phase einmal festgelegt haben. Bei allen Ableitungen würde dann automatisch der Stil angewendet. Aber der Designer nimmt Ihren Stil nicht zur Kenntnis. Sie müssen Ihre App ausführen, um zu sehen, wie der Stil angewendet wird. Ich vermute, der Designer ist einfach führt InitializeComponent aus (dies ist automatisch/vom Designer generierter Code), sodass XAML angewendet wird, jedoch kein benutzerdefinierter Code-Behind.

Daher würde ich sagen, dass explizit angegebene Stile am wenigsten funktionieren. Sie können jedenfalls Aspekte des Stils zentral ändern.

46
Gishu

Weiß, das ist Jahre später, aber da ist die Frage noch hier oben ...

  1. Erstellen Sie ein Ressourcenwörterbuch in Ihrem Projekt (Klicken Sie mit der rechten Maustaste auf das Projekt ...)

    Ich werde einen neuen Ordner unter dem Projekt namens "Assets" erstellen und "resourceDict.XAML" darin ablegen.

  2. Fügen Sie den Code zu resourceDict.XAML hinzu:

    <Style x:Key="WindowStyle" Target Type="Window" >
         <Setter Property="Background" Value="Blue" />
    </Style>
    
  3. Fügen Sie in Ihrer Project XAML-Datei unter Fenster Folgendes hinzu:

    <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>
    

    verweisen Sie auf die folgende Website: Probleme beim Verweisen auf ein Ressourcenwörterbuch, das ein zusammengeführtes Wörterbuch enthält "Es gibt einen Fehler: Wenn alle Ihre Standardstile in zusammengeführten Wörterbüchern drei Ebenen tief (oder tiefer) verschachtelt sind, ist dies im obersten Wörterbuch der Fall nicht markiert werden, so dass die Suche es überspringt. Die Lösung besteht darin, einen Standardstil für etwas, irgendetwas, im Stammwörterbuch festzulegen. " Und es scheint die Dinge zuverlässig zu regeln. Stelle dir das vor...

  4. Und zum Schluss unter Window, vielleicht nach Title, aber vor dem letzten Window '>':

    Style="{DynamicResource windowStyle}"
    
  5. Und Sie müssen den Code in den Schritten 3 und 4 zu jedem Projekt hinzufügen, auf das der Stil angewendet werden soll.

  6. Wenn Sie einen Verlaufshintergrund anstelle einer Volltonfarbe verwenden möchten, fügen Sie der resourceDict.XAML den folgenden Code hinzu:

    <LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0"
            EndPoint="0,1" >
    <GradientStop Color= "AliceBlue" Offset="0" />
    <GradientStop Color= "Blue" Offset=".75" />
    </LinearGradientBrush>
    
  7. Und ändern Sie Ihren Style Setter, damit die Hintergrundfarbe lautet:

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

Die Schritte 3 und 4 müssen in jeder project.XAML-Datei wie oben beschrieben wiederholt werden. Sie erhalten jedoch ein einheitliches Windows für die gesamte Lösung. Der gleiche Vorgang kann auch für alle Steuerelemente angewendet werden, die einheitlich aussehen sollen, Schaltflächen, unabhängig davon, was auch immer.

Wenn jemand so spät kommt, hoffe ich, dass dies hilft, da ich sicher bin, dass die ursprünglichen Poster dies alles vor Jahren herausgefunden haben.

Paul

20
Paul1307

Der Designer funktioniert nicht, weil Sie eine DynamicResource angeben. Bitte ändern Sie dies in StaticResource und alles wird gut.

Um sie auf alle Fenster anzuwenden, müssen Sie den x: Key aus dem Stil entfernen. Durch das implizite Festlegen des TargetType wird der x: Key auf den Wert in TargetType festgelegt. Bei meinen Tests funktioniert dies jedoch nicht, daher prüfe ich dies.

Wenn ich TargetType auf x: Type TextBlock setze, funktioniert der Designer einwandfrei. Es scheint nur das Fenster zu sein, das ein anderes Verhalten zeigt.

8
Ray Booysen

Sie können diesen Code zu Ihrer App.xaml.cs-Datei hinzufügen:

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

Danach gilt der auf den Typ Window angewendete Stil auch für alle Typen, die von Window abgeleitet sind.

4
STiLeTT

Ich habe das jetzt einige Tage lang untersucht und es durch den Konstruktor meiner benutzerdefinierten Fensterklasse funktionieren lassen:

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
        }
}

Hoffe es hilft jemandem

3
KroaX

Für diejenigen, die mit der Lösung des Problems zu kämpfen haben: Wie kann ich einen benutzerdefinierten Stil für alle von Windows abgeleiteten Typen automatisch anwenden lassen? Unten ist die Lösung, die ich mir ausgedacht habe

ANMERKUNG: Ich wollte wirklich nicht vom Fenstertyp ableiten oder XAML in jedes Fenster einfügen, um aus projektspezifischen Gründen eine Stilaktualisierung usw. zu erzwingen layout/windows etc.) also war ich wirklich motiviert um eine lösung zu finden, die funktionierte, dass ich bereit war, mit irgendwelchen nebenwirkungen umzugehen

Sie müssen alle instanziierten Fenster durchlaufen und sie einfach zwingen, den neuen benutzerdefinierten Stil zu verwenden, den Sie für den Fenstertyp definiert haben. Dies funktioniert gut für Fenster, die bereits geöffnet sind, aber wenn ein Fenster oder ein untergeordnetes Fenster instanziiert wird, wird es nicht wissen, ob der neue/benutzerdefinierte Typ verwendet wird, der für seinen Basistyp deklariert wurde. der Vanille-Fenstertyp. Das Beste, was ich mir einfallen lassen konnte, war, den LostKeyBoardFocus im Hauptfenster zu verwenden, wenn er den Fokus auf ein Unterfenster verliert (IOW, wenn ein Unterfenster erstellt wurde) und dann dieses FixupWindowDerivedTypes () aufzurufen.

Wenn jemand eine bessere Lösung für das "Erkennen" hat, wann ein von einem Fenster abgeleiteter Typ instanziiert wird, und daher FixupWindowDerivedTypes () aufruft, wäre das großartig. Auch in diesem Bereich kann die Behandlung von WM_WINDOWPOSCHANGING hilfreich sein.

Diese Lösung ist also nicht per se elegant, sondern erledigt die Aufgabe, ohne dass ich Code oder XAML in Verbindung mit meinen Fenstern berühren muss.

   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

In Anbetracht der Antwort von Gish habe ich eine weitere Problemumgehung gefunden. Aber es könnte ein bisschen komisch sein. Wenn Sie ein MVVM-Muster verwenden, können Sie den Code-Behind Ihres Fensters und das x: Class-Markup in der XAML-Datei entfernen. Sie erhalten also eine Instanz des Fensters oder Ihres benutzerdefinierten Fensters, jedoch keine Instanz der 'MainWindow'-Klasse, die von der' Window'-Klasse abgeleitet und als partiell markiert ist. Ich mache VS-like Fenster, also musste ich Fensterklasse erben und es Funktionalität erweitern. In diesem Fall ist es möglich, eine neue Fensterklasse als partiell zu definieren, sodass Code-Behind ohne Vererbung erstellt werden kann.

0
Crossman