2009-04-24 12 views
6

Sto cercando di rendere la mia applicazione più personalizzabile consentendo agli utenti di selezionare un colore da una finestra di dialogo Color Picker e quindi di modificare lo stile dell'applicazione in tempo reale (con DynamicResource)WPF: modifica delle risorse (colori) da App.xaml durante il runtime

Come faccio a cambiare risorse specifiche che risiedono nello app.xaml?


ho provato qualcosa di simile, ma senza fortuna (solo una prova):

var colorDialog = new CustomControls.ColorPickerDialog(); 
var dResult = colorDialog.ShowDialog(); 
var x = Application.Current.Resources.Values.OfType<LinearGradientBrush>().First(); 
x = new LinearGradientBrush(); 
x.GradientStops.Add(new GradientStop(colorDialog.SelectedColor,1)); 

Questo un estratto del file app.xaml:

<Application.Resources> 
     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="HeaderBackground"> 
      <GradientStop Color="#82cb02" Offset="1"/> 
      <GradientStop Color="#82cb01" Offset="0.2"/> 
      <GradientStop Color="#629a01" Offset="0.5"/> 
     </LinearGradientBrush> 

Qual è la migliore modo per consentire questa forma di personalizzazione (in pratica solo cambiando alcuni colori) a un'applicazione?


[Update]

Ho appena trovato this answer da una domanda precedente che è stato chiesto, e l'ho provato, ma io sono sempre lo stesso InvalidOperationException eccezione Petoj citato nei commenti per la data risposta. Ecco il codice di esempio dalla risposta:

Xaml:

<LinearGradientBrush x:Key="MainBrush" StartPoint="0, 0.5" EndPoint="1, 0.5" > 
    <GradientBrush.GradientStops> 
     <GradientStop Color="Blue" Offset="0" /> 
     <GradientStop Color="Black" Offset="1" /> 
    </GradientBrush.GradientStops> 
</LinearGradientBrush> 

C#:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush; 
myBrush.GradientStops[0].Color = Colors.Red; 

risposta

13

Sembra che tu stia provando a fare una specie di scuoiatura?

Si consiglia di definire le risorse in un dizionario delle risorse contenuto in un file separato. Poi nel codice (App.cs per caricare un default, poi altrove per cambiare) è possibile caricare le risorse come così:

//using System.Windows 
ResourceDictionary dict = new ResourceDictionary(); 
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative); 

Application.Current.Resources.MergedDictionaries.Add(dict); 

Si potrebbe anche definire il dizionario risorse predefinito in App.xaml e scaricarlo in codice appena bene.

Utilizzare l'oggetto MergedDictionaries per modificare il dizionario che si sta utilizzando in fase di esecuzione. Funziona come un fascino per cambiare un'intera interfaccia rapidamente.

1

Si ottiene un'eccezione perché si sta cercando di modificare un oggetto ghiacciato. Tutte le risorse a livello di applicazione vengono automaticamente bloccate se sono freezable e LinearGradientBrush. Se lo aggiungi a un livello inferiore come il livello della finestra, funzionerà.

+0

Ma non posso aggiungerlo in una finestra perché questo stile si applica a tutte le finestre del mio progetto –

6

Modifica risorse ampia applicazione in fase di esecuzione è come:

Application.Current.Resources("MainBackgroundBrush") = Brsh 

Circa l'InvalidOperationException, credo WallStreet programmatore è giusto. Forse non dovresti provare a modificare un pennello esistente, ma invece crea un nuovo pennello nel codice con tutti i gradiente che ti servono, e quindi assegna questo nuovo pennello alle risorse dell'applicazione.

Un altro approccio su come cambiare il colore di alcuni GradientStops è quello di definire quei colori come riferimenti DynamicResource a un'applicazione in tutto SolidColorBrushes come:

<LinearGradientBrush x:Key="MainBrush" StartPoint="0, 0.5" EndPoint="1, 0.5" > 
<GradientBrush.GradientStops> 
    <GradientStop Color="{DynamicResource FirstColor}" Offset="0" /> 
    <GradientStop Color="{DynamicResource SecondColor}" Offset="1" /> 
</GradientBrush.GradientStops> 

e quindi utilizzare

Application.Current.Resources["FirstColor"] = NewFirstColorBrsh 
Application.Current.Resources["SecondColor"] = NewSecondColorBrsh 

HTH

+0

Questo è esattamente ciò che volevo. –

+0

Si noti che questo non funziona in Silverlight. 'DynamicResource' non è supportato. – mbomb007

2

Utilizzare Clone() metodo per effettuare una copia completa del pennello (o qualsiasi altro oggetto Freezable come Storyboard) e poi usarlo:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush; 
myBrush = myBrush.Clone(); 
myBrush.GradientStops[0].Color = Colors.Red; 

@WallstreetProgrammer è giusto - tutte le risorse a livello di applicazione sono congelate per impostazione predefinita.

Ecco perché è necessario prima clonare l'oggetto.

Problemi correlati