开发者

How to apply a style to a class and its descendants?

I want to apply the following style to all controls that derive from ButtonBase

<Style
    TargetType="{x:Type ButtonBase}">
    <Setter
        Property="Cursor"
        Value="Hand" />
</Style>

But it only works for a given class, not for its descendants. How to achieve what I intend 开发者_运维知识库to?


This doesn't work because when an element doesn't have a style explicitly assigned, WPF finds its style by calling FindResource, using the element's type as the key. The fact that you've created a style whose key is ButtonBase doesn't matter: WPF finds the style with the key of Button or ToggleButton and uses it.

An inheritance-based lookup method would look up the style using the element's type, and then use the base type if no style for the element's type was found (and keep on going until it either found a style or hit FrameworkElement). The problem is that only works if no match is found - i.e. if there's no default style for Button, which of course there is.

There are two things you can do. One is to do what Jens suggests, using the style's BasedOn property to implement your own hierarchy of styles. That's kind of annoying, though, because you have to define a style for every single type; if you don't, the default WPF style for that type will be used.

Another way is to use a StyleSelector that implements this lookup behavior. Like this:

public class InheritanceStyleSelector : StyleSelector
{
    public InheritanceStyleSelector()
    {
        Styles = new Dictionary<object, Style>();
    }
    public override Style SelectStyle(object item, DependencyObject container)
    {
        Type t = item.GetType();
        while(true)
        {
            if (Styles.ContainsKey(t))
            {
                return Styles[t];
            }
            if (t == typeof(FrameworkElement) || t == typeof(object))
            {
                return null;
            }
            t = t.BaseType;
        }
    }

    public Dictionary<object, Style> Styles { get; set; }
}

You can create an instance of this, give it a set of styles, and then attach it to any ItemsControl:

<Window x:Class="StyleSelectorDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:StyleSelectorDemo="clr-namespace:StyleSelectorDemo" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <StyleSelectorDemo:InheritanceStyleSelector x:Key="Selector">
            <StyleSelectorDemo:InheritanceStyleSelector.Styles>
                <Style x:Key="{x:Type ButtonBase}">
                    <Setter Property="ButtonBase.Background"
                            Value="Red" />
                </Style>
                <Style x:Key="{x:Type ToggleButton}">
                    <Setter Property="ToggleButton.Background"
                            Value="Yellow" />
                </Style>
            </StyleSelectorDemo:InheritanceStyleSelector.Styles>
        </StyleSelectorDemo:InheritanceStyleSelector>
    </Window.Resources>
    <Grid>
        <ItemsControl ItemContainerStyleSelector="{StaticResource Selector}">
            <Button>This is a regular Button</Button>
            <ToggleButton>This is a ToggleButton.</ToggleButton>
            <TextBox>This uses WPF's default style.</TextBox>
        </ItemsControl>
    </Grid>
</Window>


This indeed seems to be a limitation of the styling system.

Faced with this problem, I declared some base style, and "sub-styled" this for every descendant I cared about.

<Style x:Key="ButtonBaseStyle" TargetType="{x:Type ButtonBase}">
    <!-- Style stuff -->
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonBaseStyle}">
    <!-- Additional style stuff for button only -->
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource ButtonBaseStyle}">
    <!-- Additional style stuff for toggle button only -->
</Style>
<!-- more ButtonBase descendants here  -->
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜