我想让ComboBoxes在我的Windows10应用程序中有主题颜色(一个有绿色的主题,一个有橙色的theme...etc)。我可以为每一种不同的颜色制作不同的样式,但这会增加大量的标记,这是一个混乱的管理。因为它们也是样式,所以我看到绑定不起作用,因为样式一旦初始化就会被密封。
有没有人想出一种方法,只改变一种样式的颜色,而不必制造多个不同的样式?
发布于 2015-08-12 14:12:00
对于这个问题,WPF有一些很好的标记。您可以使用DynamicResource
在每次资源更改时允许样式刷新。下面是一个例子:
<SolidColorBrush x:Key="ColourAccent">#448AFF</SolidColorBrush>
<Style TargetType="Button">
<Setter Property="Background" Value="{DynamicResource ColourAccent}"/>
</Style>
当然,这是该方法的一个非常简单的实现,但本质上,DynamicResource
是对ColourAccent
的引用,如果要更改资源,它将自动反映样式中的更改。
现在,更改资源是一个稍微不同的问题,对于主题化(您的样式),您需要在某个地方放置所有颜色,这里的解决方案是使用多个ResourceDictionaries
和使用MergedDictionaries
。让我告诉你我的意思:
首先,向您的项目添加一个名为Themes的文件夹,这样只会使事情变得更简单。另外,将前面提到的Style
添加到Window.Resources
或App.Resources
中,这是非常重要的。
您需要向文件夹中添加一个Amber.xaml),文件(称为ResourceDictionary
文件),如下所示:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Amber -->
<SolidColorBrush x:Key="ColourAccent">#FFC107</SolidColorBrush>
</ResourceDictionary>
这里有一个简单的资源字典,它包含一个名为ColourAccent
的资源,现在我们需要创建另一个资源(称为Blue.xaml),但是颜色不同:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Blue -->
<SolidColorBrush x:Key="ColourAccent">#448AFF</SolidColorBrush>
</ResourceDictionary>
这里的魔法很快就会变得清晰起来。拥有具有相同名称的资源的多个资源字典,将允许您创建主题。其方法是将当前资源字典替换为新的资源字典,这样做,DynamicResource
将注意到发生了更改,并刷新控件样式。
现在您有了两个资源字典,您需要计算出使用使用的字典。首先,我们需要定义应用程序将要使用的默认资源字典,您需要在App.xaml
中声明这一点。
<Application ...>
<Application.Resources>
<ResourceDictionary>
...
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourNamespace;component/Themes/Amber.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
在这里,您将看到MergedDictionaries
元素,这就是魔术发生的地方。如果你现在运行这个应用程序,你应该会看到任何按钮都会有琥珀的背景颜色。很酷是吧?
现在,它变得更加棘手,我们将删除当前在字典中的资源字典,并将其替换为不同的主题(不同的资源字典)。
这里有一些C#可以这样做:
免责声明:我只是把这些代码放在一起,几乎可以肯定有一个更好的方法,但是你明白了。将下面的代码放在鼠标单击事件中,或者放在您可以逐步执行以查看正在发生的事情的某个地方。
首先,从合并的字典中删除当前的主题。
//Find the current dictionary
ResourceDictionary oldDictionary = App.Current.Resources.MergedDictionaries.FirstOrDefault();
//If we found one, remove it.
if (dictionary != null)
App.Current.Resources.MergedDictionaries.Remove(oldDictionary);
现在我们只需要添加一个不同的资源字典。为了举个例子,我将添加Blue主题:
//Declare some variables.
string folderPath = "/YourNamespace;component/Themes/";
string desiredTheme = "Blue";
//Create the new resource dictionary
ResourceDictionary newDictionary = new ResourceDictionary();
newDictionary.Source = new Uri(string.Format("{0}{1}.xaml", folderPath, desiredTheme), UriKind.RelativeOrAbsolute);
//Add the resource dictionary to the merged dictionaries.
App.Current.Resources.MergedDictionaries.Add(newDictionary);
如果一切顺利,应用程序中任何按钮的背景都应该是Blue。万岁!
使用此方法(实质上是创建多个资源字典,每个资源都以相同的名称命名),您可以为应用程序创建多个主题。这不限于颜色,你可以有整个风格,是特定的主题,其中一个主题可能显示一个完全不同的方式作为另一个风格。做个实验,看看你能想出什么。祝好运!
https://stackoverflow.com/questions/31958128
复制相似问题