>我有两个主题:Aero.NormalColor.xaml和Classic.xaml。我的窗户上有按钮。
<Grid>
<Button Grid.Row="0"
Name="_first"
Content="Fisrt">
</Button>
</Grid>
我在 bouth 主题中为Button
定义了样式。
在 Aero.NormalColor.xaml 中:
<Style TargetType="{x:Type ButtonBase}">
<Setter Property="Background" Value="Red"/>
</Style>
在 Classic.xaml 中:
<Style TargetType="{x:Type ButtonBase}">
<Setter Property="Background" Value="Violet"/>
</Style>
并像这样设置程序集属性。
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly,
ResourceDictionaryLocation.SourceAssembly)]
我希望当选择Aero主题时 - 按钮将被Red
,当选择经典主题时 - 按钮将被Violet
。但什么也没发生。无论选择什么主题,按钮都具有默认Gray
颜色。我做错了什么?
解决方案。结果比我想象的要复杂得多,但现在它起作用了。
首先创建一个派生按钮:
public partial class ImageButton : Button
{
// Very important!
static ImageButton()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(ImageButton),
new FrameworkPropertyMetadata(typeof(ImageButton)));
}
public ImageButton()
{
InitializeComponent();
}
}
<Button x:Class="TestProjectTheme.ImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Button>
其次,正确设置程序集属性:
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly,
ResourceDictionaryLocation.SourceAssembly)]
第三,定义窗口主题的资源字典:
Aero.NormalColor.xaml
<Style TargetType="{x:Type Local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Local:ImageButton}">
<Border Background="Aquamarine">
<ContentPresenter
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
经典.xaml
<Style TargetType="{x:Type Local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Local:ImageButton}">
<Border Background="Red">
<ContentPresenter
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
第四,在主窗口中定义一个图像按钮:
<Local:ImageButton Content="look here!"
Width="100"
Height="100">
</Local:ImageButton>
第五,在Windows->Personalizaton中运行应用程序并将主题从经典切换到Aero,反之亦然第六 - 享受:)
不幸的是,在 WPF 中切换主题的机制比看起来要复杂得多。 Here
您可以看到有关此的信息和解决方案,请引用:
我想得越多,我就越意识到所有这些问题都是由于我将系统主题(aero.normalcolor(作为实际系统主题之上的样式应用而不是实际更改它的事实引起的。因此,我开始了 Reflector 的旅程,以了解 WPF 如何选择当前主题。这听起来很难,实际上比听起来要难得多。经过十几个小时(分散在几周内(和一个非常接近的博客的一些指导(不幸的是,我的链接现在已经死了(,我发现但是 WPF 在 uxtheme 中调用本机方法.dll以获取实际的系统主题,然后将结果存储在
MS.Win32.UxThemeWrapper
中,一个内部静态类(当然(。此外,类的属性是只读的(也标记为内部(,因此更改它的最佳方法是直接操作私有字段。
通常,切换主题由"手"完成。
例:
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Themes/DefaultSkin.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
App.xaml.cs
public partial class App : Application
{
public void ChangeTheme(Uri uri)
{
var resourceDict = Application.LoadComponent(uri) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDict);
}
}
MainWindow.xaml
<StackPanel>
<Button Width="100" Height="100" Content="Test" />
<Button Width="100" Height="100" Content="Click Me" Click="Button_Click" />
</StackPanel>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var app = App.Current as App;
app.ChangeTheme(new Uri(@"/Resources/Themes/BlueSkin.xaml", UriKind.Relative));
}
}
DefaultSkin.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
BlueSkin.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Blue" />
</Style>
</ResourceDictionary>