我试图通过允许用户从拾色器对话框中选择一种颜色,然后实时更改应用程序的样式(使用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;
答案 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是,则自动冻结所有应用程序级资源。如果你将它添加到较低级别,如窗口级别,它将工作。