WPF:在运行时期间从App.xaml更改资源(颜色)

时间:2009-04-24 14:53:05

标签: wpf xaml resources customization app.xaml

我试图通过允许用户从拾色器对话框中选择一种颜色,然后实时更改应用程序的样式(使用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>

允许这种形式的可自定义(基本上只是更改某些颜色)到应用程序的最佳方法是什么?


[更新]

我刚刚从之前提出的问题中找到了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;

4 个答案:

答案 0 :(得分:14)

看起来你正试图做某种剥皮?

我建议在单独文件中包含的资源字典中定义资源。然后在代码中(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 :(得分:11)

在运行时更改应用程序范围的资源就像:

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

关于InvalidOperationException,我想WallStreet Programmer是对的。 也许您不应该尝试修改现有的画笔,而是在代码中创建一个新的画笔,其中包含您需要的所有渐变效果,然后在应用程序资源中分配这个新画笔。

另一种改变某些GradientStops颜色的方法是将这些颜色定义为对Application Wide SolidColorBrushes的DynamicResource引用,如:

<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 :(得分:2)

使用Clone()方法制作画笔(或任何其他可冻结对象,如Storyboard)的深层副本,然后使用它:

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

@WallstreetProgrammer是对的 - 默认情况下冻结所有应用程序级资源。

这就是为什么你需要先克隆对象。

答案 3 :(得分:1)

您遇到异常,因为您正在尝试修改冻结对象。如果它们是可冻结的并且LinearGradientBrush是,则自动冻结所有应用程序级资源。如果你将它添加到较低级别,如窗口级别,它将工作。