我想下面的樣式應用到從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 -->