在WPF中,我该如何获取当前主题的按钮背景?

6
在我的WPF应用程序中,我需要获取主题按钮的背景画刷以绘制另一个控件的背景。
我已经试过引用PresentationFramework.Aero.dll并使用ButtonChrome,但迄今为止没有成功。
我也尝试了使用VisualStyleRenderer,但似乎这个类只能用于绘制背景(我无法获取画刷并将其设置为另一个控件的背景)。
有什么想法吗?
诚挚问候, Eduardo Melo
1个回答

9
可以通过在资源中查找默认按钮样式来在代码中完成此操作:
    private static object GetValueFromStyle(object styleKey, DependencyProperty property)
    {
        Style style = Application.Current.TryFindResource(styleKey) as Style;
        while (style != null)
        {
            var setter =
                style.Setters
                    .OfType<Setter>()
                    .FirstOrDefault(s => s.Property == property);

            if (setter != null)
            {
                return setter.Value;
            }

            style = style.BasedOn;
        }
        return null;
    }

    ...

    this.Background = GetValueFromStyle(typeof(Button), BackgroundProperty) as Brush;

如果你需要在XAML中完成它,你可以很容易地从上面的代码创建一个标记扩展:

public class ValueFromStyleExtension : MarkupExtension
{
    public ValueFromStyleExtension()
    {
    }

    public object StyleKey { get; set; }
    public DependencyProperty Property { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (StyleKey == null || Property == null)
            return null;
        object value = GetValueFromStyle(StyleKey, Property);
        if (value is MarkupExtension)
        {
            return ((MarkupExtension)value).ProvideValue(serviceProvider);
        }
        return value;
    }

    private static object GetValueFromStyle(object styleKey, DependencyProperty property)
    {
        Style style = Application.Current.TryFindResource(styleKey) as Style;
        while (style != null)
        {
            var setter =
                style.Setters
                    .OfType<Setter>()
                    .FirstOrDefault(s => s.Property == property);

            if (setter != null)
            {
                return setter.Value;
            }

            style = style.BasedOn;
        }
        return null;
    }
}

XAML

Background="{util:ValueFromStyle StyleKey={x:Type Button}, Property=Control.Background}">

编辑:修复 ValueFromStyleExtension 对于将值定义为 DynamicResource(或另一个 ME)的情况。


只有一件事:对于那些遇到“MS.Internal.Markup.MarkupExtensionParser+UnknowMarkupExtension”错误的人,这里有一个解决方案:http://www.hardcodet.net/2008/04/nested-markup-extension-bug - Carlos Melo
你的意思是,如果在样式中定义为DynamicResource?不,它不会自动更新。为此,ME必须返回DynamicResource标记扩展,但出于某种原因,当我尝试时似乎无法工作... - Thomas Levesque
是的,那就是我想说的。你能否编辑上面的代码以包括DynamicResource的返回?我真的不知道MarkupExtensions的任何内容,我认为它可以帮助我更好地理解它。 - Carlos Melo
就像我说的,我尝试过了但是没有成功;我不知道如何修复它。 - Thomas Levesque
好的。我尝试使用触发器的方法,但最终放弃了。用户更改主题的频率并不高,无论如何还是谢谢! - Carlos Melo
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接