可湿性工作基金会。主题中定义的样式不起作用



>我有两个主题: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>

相关内容

  • 没有找到相关文章