将默认Button样式应用于自定义Button类

时间:2014-11-17 11:51:31

标签: wpf xaml

我创建了一个继承自Button的自定义IconButton类,并添加了一些依赖项属性,将图像放在按钮文本的前面。

代码开头如下:

public partial class IconButton : Button
{
    // Dependency properties and other methods
}

它带有一个如下所示的XAML文件:

<Button x:Class="Unclassified.UI.IconButton" x:Name="_this" ...>
    <Button.Template>
        <ControlTemplate>
            <Button
                Padding="{TemplateBinding Padding}"
                Style="{TemplateBinding Style}"
                Focusable="{TemplateBinding Focusable}"
                Command="{TemplateBinding Button.Command}">

                <StackPanel ...>
                    <Image .../>
                    <ContentPresenter
                        Visibility="{Binding ContentVisibility, ElementName=_this}"
                        RecognizesAccessKey="True"
                        Content="{Binding Content, ElementName=_this}">
                        <ContentPresenter.Style>
                            ...
                        </ContentPresenter.Style>
                    </ContentPresenter>
                </StackPanel>
            </Button>
        </ControlTemplate>
    </Button.Template>
</Button>

到目前为止效果很好。 (但是如果你知道一种更简单的方法来覆盖Button的内容而不改变整个模板并在Button中放置一个Button,请告诉我。每当我尝试时,Visual Studio 2010 SP1会在我关闭最终XML标签时立即崩溃。)

现在我已经添加了一些代码来修复WPF破解的Windows 8的Aero2主题。它是一个单独的ResourceDictionary,它会覆盖各种默认样式:(Based on thisvia here

<ResourceDictionary ...>
    <Style TargetType="{x:Type Button}">
        ...
    </Style>
</ResourceDictionary>

新的ResourceDictionary在启动时添加到Application Resources,在App.xaml.cs中:

protected override void OnStartup(StartupEventArgs args)
{
    base.OnStartup(e);
    // Fix WPF's dumb Aero2 theme if we're on Windows 8 or newer
    if (OSInfo.IsWindows8OrNewer)
    {
        Resources.MergedDictionaries.Add(new ResourceDictionary
        {
            Source = new Uri("/Resources/RealWindows8.xaml", UriKind.RelativeOrAbsolute)
        });
    }
    ...
}

这也适用于我放在XAML视图中的普通Button控件。 (我仍在寻找find out the real Windows theme的方法,而不是依赖版本号。)

但我的IconButton控件不考虑这些新的默认值,并且仍然基于WPF的内置Button样式,这是非常基本的。 (它实际上只是一个没有Win32显示的所有细节和交互性的紧凑矩形。)

我想我需要一种方法告诉我的IconButton应该重新评估基本样式并查看新添加的RealWindows8样式。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

我找到了解决方案。有两种方法可以实现这一目标。任何一个都足够了。

XAML方式:

将Style属性添加到派生控件。这将新控件的样式明确地预设为应用程序中定义为Button样式的任何样式。 StaticResource就足够了。如果在使用派生控件的位置指定了不同的样式,则将替换此初始值。

<Button Style="{StaticResource {x:Type Button}}" ...>
    ...
</Button>

代码(-behind)方式:

在派生类的构造函数中调用SetResourceReference方法。

public IconButton()
{
    // Use the same style as Button, also when it is overwritten by the application.
    SetResourceReference(StyleProperty, typeof(Button));
    ...
}

我已经为我的IconButton测试了这个,以及派生的TabControl和TabItem类。

Source