如何将一个样式应用于一个类及其后代?

Jad*_*ias 6 .net wpf xaml styles button

我想将以下样式应用于派生自的所有控件 ButtonBase

<Style
    TargetType="{x:Type ButtonBase}">
    <Setter
        Property="Cursor"
        Value="Hand" />
</Style>
Run Code Online (Sandbox Code Playgroud)

但它只适用于给定的类,而不适用于它的后代.如何实现我的目的?

Rob*_*ney 4

这是行不通的,因为当元素没有显式指定样式时,WPF 会FindResource使用元素的类型作为键来调用 来查找其样式。事实上,您创建的样式的键为并不重要:WPF 会查找键为或 的ButtonBase样式ButtonToggleButton并使用它。

基于继承的查找方法将使用元素的类型查找样式,如果找不到元素类型的样式,则使用基本类型(并继续查找,直到找到样式或 hit FrameworkElement)。问题是,只有在没有找到匹配项的情况下才有效 - 即,如果 没有默认样式Button,当然有。

您可以做两件事。一种是按照 Jens 的建议,使用样式的BasedOn属性来实现您自己的样式层次结构。但这有点烦人,因为您必须为每种类型定义一种样式;如果不这样做,将使用该类型的默认 WPF 样式。

另一种方法是使用StyleSelector实​​现此查找行为的 a 。像这样:

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; }
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个实例,为其指定一组样式,然后将其附加到任何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>
Run Code Online (Sandbox Code Playgroud)