我想下面的样式应用到从ButtonBase
如何将样式应用于类和它的后代?
<Style
TargetType="{x:Type ButtonBase}">
<Setter
Property="Cursor"
Value="Hand" />
</Style>
获得的所有控件,但它仅适用于一个给定的类,而不是它的后代。如何实现我的目标?
我想下面的样式应用到从ButtonBase
如何将样式应用于类和它的后代?
<Style
TargetType="{x:Type ButtonBase}">
<Setter
Property="Cursor"
Value="Hand" />
</Style>
获得的所有控件,但它仅适用于一个给定的类,而不是它的后代。如何实现我的目标?
这不起作用,因为当一个元素没有风格明确分配,WPF通过调用FindResource
,使用元素的类型为关键认定其风格。事实上,您创建的关键是ButtonBase
的样式并不重要:WPF使用Button
或ToggleButton
的关键字查找样式并使用它。
基于继承的查找方法将使用元素的类型来查找样式,然后在没有找到元素类型的样式的情况下使用基本类型(并继续前进,直到找到样式或点击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>
这确实似乎是造型系统的限制。
面对这个问题,我宣布了一些基本风格,并为我关心的每一个后代“分”风格。
<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 -->