Это не работает, потому что, когда элемент не имеет явно назначенного стиля, WPF находит свой стиль, вызывая FindResource
, используя тип элемента в качестве ключа.Тот факт, что вы создали стиль с ключом ButtonBase
, не имеет значения: WPF находит стиль с ключом Button
или ToggleButton
и использует его.
Поиск на основе наследованияМетод будет искать стиль, используя тип элемента, а затем использовать базовый тип, если стиль для типа элемента не найден (и продолжать работу, пока не найдет стиль или не нажмет FrameworkElement
).Проблема в том, что работает, только если совпадение не найдено - то есть, если для Button
нет стиля по умолчанию, что, конечно, есть.
Есть две вещи, которые вы можете сделать.Один из них - сделать то, что предлагает Дженс, используя свойство стиля 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>