ВПФ:Изменение ресурсов (цветов) из App.xaml во время выполнения

StackOverflow https://stackoverflow.com/questions/786183

Вопрос

Я пытаюсь сделать свое приложение более настраиваемым, позволяя пользователям выбирать цвет из диалогового окна «Выбор цвета», а затем меняя стиль приложения в реальном времени (с помощью 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>

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


[Обновлять]

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

Ксамл:

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

С#:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush;
myBrush.GradientStops[0].Color = Colors.Red;
Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

<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

ХТХ

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top