2013-01-17 8 views
10

Ich bin dabei, eine Basis-Fenster-Klasse für die meisten meiner Fenster zu erstellen, von ableiten. Offensichtlich war die beste Lösung dafür eine separate Klasse und ein Stil, der darauf zutrifft.WPF-Stil für Basis-Fenster nicht in App.xaml angewendet, aber in Designs/Generic.xaml

Das Problem ist, dass die <Style ../> ich habe nicht angewendet wird, wenn es in App.Resources ist. Das heißt, wenn es in einem externen ResourceDictionary definiert ist und in Ressourcen App.xaml oder ein lokales Wörterbuch zusammengeführt und zusammengeführt oder in App.Resources inline platziert. Die <Style ../> wird jedoch angewendet, wenn sie in Themes/Generic.xaml platziert wird.

Das Problem kann demonstriert werden, ohne irgendetwas im Basisfenster außer dem Überschreiben der DefaultStyleKeyProperty irgendetwas besonders zu tun.

Unten ist ThemeWindow:

public class ThemeWindow : Window 
{ 
    static ThemeWindow() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(typeof(ThemeWindow))); 
    } 
} 

Hier ist die sehr einfache <Style ../> ist den ich versuche zu bewerben (es macht die Window Hintergrund rot, nichts mehr):

<Style TargetType="{x:Type testing:ThemeWindow}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type testing:ThemeWindow}"> 
       <Grid> 
        <Grid.Background> 
         <SolidColorBrush Color="Red"/> 
        </Grid.Background> 
        <AdornerDecorator> 
         <ContentPresenter /> 
        </AdornerDecorator> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Die MainWindow die ThemeWindow verwendet , ist einfach die folgende XAML:

<testing:ThemeWindow x:Class="Testing.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:testing="clr-namespace:Testing" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Button Content="Button" HorizontalAlignment="Left" Margin="125,83,0,0" VerticalAlignment="Top" Width="75"/> 
    </Grid> 
</testing:ThemeWindow> 
01 Jetzt

, wie gesagt, wenn man das Style in seinen eigenen Platz ResourceDictionary und schließen es wie folgt aus:

<App.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="/Themes/ThemeWindow.xaml" /> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</App.Resources> 

.. es funktioniert nicht. Wenn Sie den Stil direkt in App.Resources inline, funktioniert es nicht.

Die nur Situation, die ich finden kann, ist es arbeiten, um den ResourceDictionary XAML Generic.xaml, zu nennen und in das Themes/ Verzeichnis der Anwendung zu platzieren.

Ich frage mich genau, warum das passiert.

Meine einzige Theorie ist, dass, wenn WPF einen Steuerelementtyp sieht, es zu Themes geht, und alle ResourceDictionary s für den Typ scannen, dann fällt zurück auf Generic.xaml und laden Sie es. Dies erklärt nicht, warum es nicht geladen wird, wenn die <Style /> in einem fusionierten ResourceDictionary verfügbar ist. Hinweis, dass es funktioniert, wenn die MergedDictionary in Generic.xaml platziert wird, aus offensichtlichen Gründen.

Ich bin völlig in Ordnung mit der ResourceDictionary in Generic.xaml zusammenführen müssen, wenn das ist, was ich tun muss. Ich möchte nur auf die technischen Details eingehen, warum es so sein muss.

Screenshots dieser nicht funktioniert/Arbeits: Broken Image Working Image

Antwort

3

Ich habe eine einfache Abhilfe, die Sie erlauben würde, Ihre Art zu setzen in Sie App.xaml.

Definieren Sie Ihren Stil in App.XAML wie folgt aus:

<Style x:Key="{x:Type testing:ThemeWindow}" TargetType="{x:Type testing:ThemeWindow}"> 

und ändern Sie Ihre ThemWindow dazu:

public class ThemeWindow : Window 
{ 
    static ThemeWindow() 
    { 
     StyleProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(GetDefautlStyle())); 
    } 

    private static Style GetDefautlStyle() 
    { 
     if (defaultStyle == null) 
     { 
      defaultStyle = Application.Current.FindResource(typeof(ThemeWindow)) as Style; 
     } 
     return defaultStyle; 
    } 

    private static Style defaultStyle = null; 
} 

Es ist nicht wirklich die Frage zu lösen, aber das würde ermöglichen es Ihnen, zu erreichen, was Sie brauchen!

EDIT: Mit Blick auf DefaultStyleKey Referenz, ist es klar gesagt, dass es für Thema der Stil verwendet wird. Das erklärt, warum es in app.xaml oder einem anderen Wörterbuch nicht gefunden wird. Es wird nur in Theme-Wörterbüchern gesucht. Sie müssen also entweder Ihren Stil in einem Designwörterbuch definieren oder die Style-Eigenschaft direkt wie im obigen Beispiel verwenden.

+0

Warum wollen Sie speichern 'defaultStyle' in einer statischen Variablen? Vorausgesetzt, dass dies vom statischen Konstruktor aufgerufen wird, wird es nur einmal aufgerufen ... –

+1

Ich habe diesen Code vor mehr als zwei Jahren geschrieben, also erinnere ich mich nicht ehrlich an die Motivationen dieses statischen Feldes. Sie haben offensichtlich Recht und dieses Feld ist nicht notwendig. – Sisyphe

0

Ich komme um die folgende Lösung bereits in Stackoverflow diskutiert. Beim Laden der Anwendung wäre es erforderlich, die Ladekomponente hinzuzufügen.

Refer Solution

+0

Leider ist das nicht das gleiche Problem. –