2009-04-24 32 views
6

Estoy intentando hacer que mi aplicación sea más personalizable al permitirles elegir un color desde un cuadro de diálogo Selector de color y luego cambiar el estilo de la aplicación en tiempo real (con DynamicResource)WPF: Cambio de recursos (colores) desde App.xaml durante el tiempo de ejecución

¿Cómo hago para cambiar los recursos específicos que residen en el app.xaml?


he intentado algo como esto, pero sin suerte (sólo una prueba):

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

Esto muestra un extracto del archivo 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> 

¿Cuál es la mejor forma de permitir esta forma de personalización (básicamente, simplemente cambiando algunos colores) a una aplicación?


[Actualización]

simplemente me encontré this answer de una pregunta anterior que se hizo, y probado, pero me estoy haciendo la misma InvalidOperationException excepción Petoj menciona en los comentarios de lo dado responder. Aquí está el código de ejemplo de la respuesta:

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; 

Respuesta

13

Parece que estás tratando de hacer algún tipo de desollado?

Recomiendo definir los recursos en un diccionario de recursos que se encuentra en un archivo separado. A continuación, en el código (App.cs para cargar un defecto, entonces en otro lugar a cambios) se pueden cargar los recursos de modo que:

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

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

También podría definir el diccionario de recursos predeterminado en App.xaml y descargarlo en el código justo multa.

Utilice el objeto MergedDictionaries para cambiar el diccionario que está utilizando en el tiempo de ejecución. Funciona como un encanto para cambiar una interfaz completa rápidamente.

1

Se obtiene una excepción ya que están tratando de modificar un objeto congelado. Todos los recursos de nivel de aplicación se congelan automáticamente si son freezables y LinearGradientBrush. Si lo agrega en un nivel inferior como el nivel de la ventana, funcionará.

+0

Pero no puedo agregarlo en una ventana porque este estilo se aplica a todas las ventanas de mi proyecto –

6

Cambio de aplicación amplios recursos en tiempo de ejecución es como:

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

Sobre el InvalidOperationException, supongo WallStreet programador es correcto. Quizás no deba tratar de modificar un pincel existente, sino crear un pincel nuevo en el código con todos los degradados que necesite, y luego asignar este pincel nuevo en los recursos de la aplicación.

Otro enfoque sobre cómo cambiar el color de algunos GradientStops es definir esos colores como referencias DynamicResource a la extensa aplicación SolidColorBrushes como:

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

y luego usar

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

HTH

+0

Esto es exactamente lo que quería. –

+0

Tenga en cuenta que esto no funciona en Silverlight. 'DynamicResource' no es compatible. – mbomb007

2

Utilice Clone() método para hacer una copia en profundidad de la brocha (o cualquier otro objeto congelable como Storyboard) y luego usarlo:

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

@WallstreetProgrammer es correcto - todos los recursos a nivel de aplicación son congelados por defecto.

Es por eso que primero necesita clonar el objeto.

Cuestiones relacionadas