2009-04-24 3 views
6

Я пытаюсь сделать мое приложение более настраиваемым, позволяя пользователям выбирать цвет из диалогового окна «Выбор цвета», а затем изменять стиль приложения в режиме реального времени (с DynamicResource)WPF: изменение ресурсов (цветов) из App.xaml во время выполнения

Как я могу изменить определенные ресурсы, которые находятся в app.xaml?


Я пытался что-то подобное, но не повезло (просто тест):

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

Это выдержка из файла 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> 

Что является лучшим способ позволить этой форме настраиваемости (в основном, просто изменить некоторые цвета) в приложении?


[Update]

Я только что нашел this answer из предыдущего вопроса, который был задан, и попробовал, но я получаю то же InvalidOperationException исключение Petoj упоминается в комментариях для данного ответ. Вот пример кода из ответа:

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; 

ответ

13

Похоже, вы пытаетесь сделать что-то вроде скиннинга?

Я бы рекомендовал определить ресурсы в ресурсном словаре, содержащемся в отдельном файле. Затем в коде (App.cs для загрузки по умолчанию, то в другом месте, чтобы изменить) вы можете загрузить ресурсы таким образом:

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

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

Вы также можете определить словарь ресурсов по умолчанию в App.xaml и выгрузить его в код просто хорошо.

Используйте объект MergedDictionaries, чтобы изменить словарь, который вы используете во время выполнения. Работает как шарм для быстрого изменения всего интерфейса.

1

Вы получите исключение, потому что вы пытаетесь изменить замороженный объект. Все ресурсы уровня приложения автоматически замерзают, если они являются замороженными и LinearGradientBrush. Если вы добавите его на более низкий уровень, например, на уровне окна, он будет работать.

+0

Но я не могу добавить его в окно, потому что этот стиль применим ко всем окнам моего проекта. –

6

Изменение приложения широких ресурсов во время выполнения, как:

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

О InvalidOperationException, я думаю, WallStreet Программист прав. Возможно, вам не следует пытаться изменить существующую кисть, но вместо этого создайте новую кисть в коде со всеми необходимыми градиентными остановками, а затем назначьте эту новую кисть в ресурсах приложения.

Другой подход к проблеме изменения цвета некоторых GradientStops является определение этих цветов в качестве ссылок DynamicResource к применению Wide SolidColorBrushes как:

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

, а затем использовать

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

НТН

+0

Это именно то, что я хотел. –

+0

Обратите внимание, что это не работает в Silverlight. 'DynamicResource' не поддерживается. – mbomb007

2

Использовать Clone() способ сделать глубокую копию кисти (или любого другого объекта, как замерзающей Storyboard), а затем использовать его:

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

@WallstreetProgrammer прав - все ресурсы на уровне приложения заморожены по умолчанию.

Вот почему вам нужно сначала клонировать объект.