2009-04-24 5 views
6

Ich versuche, meine Anwendung anpassbarer zu machen, indem Benutzer eine Farbe aus einem Farbauswahldialog auswählen und dann den Stil der Anwendung in Echtzeit ändern können (mit DynamicResource)WPF: Ändern von Ressourcen (Farben) aus der App.xaml zur Laufzeit

Wie gehe ich beim Ändern bestimmter Ressourcen, die sich in der app.xaml befinden?


Ich habe so etwas wie dies aber kein Glück (nur ein Test) versucht:

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

Dies ist ein Auszug aus der app.xaml Datei:

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

Was ist der beste Möglichkeit, diese Form der Anpassbarkeit (im Grunde nur einige Farben ändern) zu einer Anwendung zu ermöglichen?


[Update]

Ich habe gerade this answer aus einer früheren Frage, die gestellt wurde, und es versucht, aber ich bin immer die gleiche InvalidOperationException Ausnahme Petoj für die gegebene in den Kommentaren erwähnt Antworten. Hier ist der Beispielcode aus der Antwort:

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; 

Antwort

13

Es sieht so aus als ob Sie versuchen, eine Art von Häutung zu machen?

Ich würde empfehlen, die Ressourcen in einem Resource Dictionary in einer separaten Datei zu definieren. Dann im Code (App.cs einen Standard zu laden, dann an andere Stelle zu ändern), um die Ressourcen so laden:

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

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

Sie könnten auch den Standard-Ressource-Wörterbuch in App.xaml definieren und in Code entladen nur fein.

Verwenden Sie das MergedDictionaries-Objekt, um das verwendete Wörterbuch zur Laufzeit zu ändern. Funktioniert wie ein Zauber, um schnell eine ganze Oberfläche zu verändern.

1

Sie erhalten eine Ausnahme, weil Sie ein gefrorenes Objekt zu ändern versuchen. Alle Ressourcen auf Anwendungsebene werden automatisch eingefroren, wenn sie Freezable und LinearGradientBrush sind. Wenn Sie es auf einer niedrigeren Ebene wie Fensterebene hinzufügen, wird es funktionieren.

+0

Aber ich kann es nicht in einem Fenster hinzufügen, da dieser Stil für jedes Fenster in meinem Projekt gilt –

6

Ändern Anwendung weite Ressourcen im laufenden Betrieb ist wie:

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

über die InvalidOperationException, ich denke, Wallstreet Programmer richtig ist. Vielleicht sollten Sie nicht versuchen, einen vorhandenen Pinsel zu modifizieren, sondern stattdessen einen neuen Pinsel im Code mit allen benötigten Gradientenanschlägen erstellen und diesen neuen Pinsel dann in Anwendungsressourcen zuweisen.

Ein weiterer Ansatz zum Ändern der Farbe einiger GradientStops ist diese Farben als Dynamic Verweise auf Anwendungs ​​Breiten SolidColorBrushes wie zu definieren:

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

und dann

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

HTH verwenden

+0

Dies ist genau das, was ich wollte. –

+0

Beachten Sie, dass dies in Silverlight nicht funktioniert. 'DynamicResource' wird nicht unterstützt. – mbomb007

2

Verwenden Sie die Clone() Methode eine tiefe Kopie der Bürste (oder einem anderen freezable Objekt wie Storyboard) herzustellen und zu verwenden es dann:

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

@WallstreetProgrammer ist richtig - alle Anwendungsebene Ressourcen sind standardmäßig eingefroren.

Deshalb müssen Sie das Objekt zuerst klonen.