2013-01-17 9 views
10

Sto creando una classe finestra di base da cui la maggior parte delle mie finestre può derivare. Ovviamente la migliore soluzione per questo era una classe separata, e uno stile che si applica ad esso.Stile WPF per la finestra di base non applicato in App.xaml, ma in Temi/Generic.xaml

Il problema è che il <Style ../> che ho non viene applicato quando è in App.Resources. Cioè, se è definito in un esterno ResourceDictionary e unificato nelle risorse di App.xaml o in un dizionario locale e unito o inserito in linea in App.Resources. Lo <Style ../> viene tuttavia applicato quando viene inserito in Themes/Generic.xaml.

Il problema può essere dimostrato senza fare nulla di speciale nella finestra di base, a parte l'override del DefaultStyleKeyProperty.

Di seguito ThemeWindow:

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

Ecco la semplice <Style ../> sto cercando di applicare (rende il Window sfondo rosso, niente di più):

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

Il MainWindow che utilizza ThemeWindow , è semplicemente il seguente 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> 

Ora, come detto, se si inserisce che Style nel proprio ResourceDictionary, e includere in questo modo:

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

.. non funziona. Se inline lo stile direttamente in App.Resources, non funziona.

La situazione unica posso trovarlo lavoro è quello di chiamare il ResourceDictionary XAML Generic.xaml, e posizionarlo nella directory Themes/ dell'applicazione.

Mi chiedo esattamente perché questo sta accadendo.

mia unica teoria è che quando WPF vede un tipo di controllo, sarà verso Themes testa, e la scansione di tutti ResourceDictionary s per il tipo, poi ripiegare a Generic.xaml e caricarlo. Questo non spiega perché non si caricherà se lo <Style /> è disponibile in un ResourceDictionary unito. Nota: che funziona se lo MergedDictionary viene inserito in Generic.xaml, per ovvi motivi.

Sto perfettamente bene a dover unire il ResourceDictionary in Generic.xaml se è quello che devo fare. Voglio solo scendere ai dettagli tecnici sul motivo per cui deve essere così.

Screenshots di questo non funziona/lavoro: Broken Image Working Image

risposta

3

Ho un soluzione semplice che permetterà di impostare il tuo stile in voi App.xaml.

Definisci il tuo stile nell'app.XAML come questo:

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

e modificare le ThemWindow a questo:

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

Non risolve veramente il problema, ma che permetterebbe di ottenere quello che ti serve!

EDIT: Guardando DefaultStyleKey di riferimento, è chiaramente indicato che è utilizzato per tema in stile ricerca. Questo spiega perché non lo troverà in app.xaml o in qualsiasi altro dizionario. Cerca solo nei dizionari dei temi. Quindi devi definire il tuo stile in un dizionario dei temi o usare direttamente la proprietà Style come nell'esempio sopra.

+0

Perché si memorizzano 'defaultStyle' in una variabile statica? Dato che questo viene chiamato dal costruttore statico, verrà chiamato una sola volta ... –

+1

Ho scritto quel codice più di due anni fa, quindi sinceramente non ricordo le motivazioni di questo campo statico. Hai ovviamente ragione e questo campo non è necessario. – Sisyphe

0

Vengo in giro la seguente soluzione già discussa in StackOverflow. avrebbe richiesto di aggiungere il componente di carico durante il caricamento dell'applicazione.

Refer Solution

+0

Sfortunatamente, non è lo stesso problema. –