我想在我的Windows 10 App中制作ComboBoxs以获得主题颜色(一个具有绿色主题,一个具有橙色主题......等)。我可以通过为每种不同的颜色制作不同的样式来做到这一点,但这会增加大量的标记并且管理起来很麻烦。因为它们也是样式,我读到绑定不会起作用,因为样式在初始化后会被密封。
有没有人想出一种方法来改变样式的颜色而不必制作多个单独的样式?
答案 0 :(得分:3)
WPF为这个问题提供了一些很好的标记。每次资源更改时,您都可以使用DynamicResource
允许样式刷新。这是一个例子:
<SolidColorBrush x:Key="ColourAccent">#448AFF</SolidColorBrush>
<Style TargetType="Button">
<Setter Property="Background" Value="{DynamicResource ColourAccent}"/>
</Style>
这当然是这个方法的一个非常简单的实现,但基本上DynamicResource
是对ColourAccent
的引用,如果要更改资源,它将自动反映样式的变化。
现在,更改资源是一个稍微不同的问题,对于主题您的样式,您需要在某处放置所有颜色,此处的解决方案是使用多个ResourceDictionaries
并使用MergedDictionaries
。让我告诉你我的意思:
首先,在您的项目中添加一个名为主题的文件夹,它会让事情变得更轻松。另外,请将前面提到的Style
添加到Window.Resources
或App.Resources
,这非常重要。
您需要在文件夹中添加ResourceDictionary
文件(将其命名为 Amber.xaml ),它看起来像这样:
<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 ),但颜色不同:< / p>
<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);
现在如果一切顺利,应用中任何按钮的背景现在应为蓝色。万岁!
使用此方法实际上是创建多个资源字典,每个资源字典都具有相同名称的资源,您可以为应用程序创建多个主题。这不仅限于颜色,您可以拥有特定主题的整个样式,其中一个主题可能以完全不同的方式显示按钮作为另一个样式。试验并看看你能想出什么。祝你好运!