WPF: изменение ресурсов (цветов) из App.xaml во время выполнения - PullRequest
9 голосов
/ 24 апреля 2009

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

Как мне изменить конкретные ресурсы, которые находятся в 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]

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

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;

Ответы [ 4 ]

14 голосов
/ 24 апреля 2009

Похоже, вы пытаетесь сделать какую-то шкуру?

Я бы порекомендовал определить ресурсы в Словаре ресурсов, содержащемся в отдельном файле. Затем в коде (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, чтобы изменить словарь, который вы используете во время выполнения. Работает как шарм за быструю смену всего интерфейса.

11 голосов
/ 27 апреля 2009

Изменение ресурсов приложения во время выполнения выглядит так:

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

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

Еще один подход к изменению цвета некоторых GradientStops - это определить эти цвета как ссылки DynamicResource на 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

HTH

2 голосов
/ 05 мая 2010

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

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

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

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

1 голос
/ 24 апреля 2009

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

...