【问题标题】:How to apply a style to a class and its descendants?如何将样式应用于类及其后代?
【发布时间】:2010-11-25 15:44:54
【问题描述】:

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

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

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

【问题讨论】:

    标签: .net wpf xaml button styles


    【解决方案1】:

    这不起作用,因为当元素没有显式分配样式时,WPF 通过调用FindResource 来查找其样式,使用元素的类型作为键。您创建了键为 ButtonBase 的样式这一事实并不重要:WPF 会找到键为 ButtonToggleButton 的样式并使用它。

    基于继承的查找方法会使用元素的类型来查找样式,如果没有找到该元素类型的样式,则使用基本类型(并继续进行,直到找到样式或点击FrameworkElement )。问题是只有在没有找到匹配项时才有效 - 即如果没有 Button 的默认样式,当然有。

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

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

    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; }
    }
    

    您可以为此创建一个实例,为其设置一组样式,然后将其附加到任何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>
    

    【讨论】:

      【解决方案2】:

      这确实似乎是样式系统的限制。

      面对这个问题,我声明了一些基本样式,并为我关心的每个后代“子样式化”了它。

      <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  -->
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-12
        • 2012-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-19
        • 2019-06-08
        相关资源
        最近更新 更多