У меня была точно такая же проблема, но для ItemsContainerStyle ... поэтому я сделал в значительной степени то, что вы сказали, и написал AttachedProperty, который позволил бы динамический ресурс для BasedOn.
DynamicResource для Style BasedOn
Вот решение, измененное для вашей ситуации:
public class DynamicStyle
{
public static Style GetBaseStyle(DependencyObject obj)
{
return (Style)obj.GetValue(BaseStyleProperty);
}
public static void SetBaseStyle(DependencyObject obj, Style value)
{
obj.SetValue(BaseStyleProperty, value);
}
// Using a DependencyProperty as the backing store for BaseStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BaseStyleProperty =
DependencyProperty.RegisterAttached("BaseStyle", typeof(Style), typeof(DynamicStyle), new UIPropertyMetadata(DynamicStyle.StylesChanged));
public static Style GetDerivedStyle(DependencyObject obj)
{
return (Style)obj.GetValue(DerivedStyleProperty);
}
public static void SetDerivedStyle(DependencyObject obj, Style value)
{
obj.SetValue(DerivedStyleProperty, value);
}
// Using a DependencyProperty as the backing store for DerivedStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DerivedStyleProperty =
DependencyProperty.RegisterAttached("DerivedStyle", typeof(Style), typeof(DynamicStyle), new UIPropertyMetadata(DynamicStyle.StylesChanged));
private static void StylesChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
if (!typeof(FrameworkElement).IsAssignableFrom(target.GetType()))
throw new InvalidCastException("Target must be FrameworkElement");
var Element = (FrameworkElement)target;
var Styles = new List<Style>();
var BaseStyle = GetBaseStyle(target);
if (BaseStyle != null)
Styles.Add(BaseStyle);
var DerivedStyle = GetDerivedStyle(target);
if (DerivedStyle != null)
Styles.Add(DerivedStyle);
Element.Style = MergeStyles(Styles);
}
private static Style MergeStyles(ICollection<Style> Styles)
{
var NewStyle = new Style();
foreach (var Style in Styles)
{
foreach (var Setter in Style.Setters)
NewStyle.Setters.Add(Setter);
foreach (var Trigger in Style.Triggers)
NewStyle.Triggers.Add(Trigger);
}
return NewStyle;
}
}
А вот пример его использования:
<!-- xmlns:ap points to the namespace where DynamicStyle class lives -->
<Button ap:DynamicStyle.BaseStyle="{DynamicResource {x:Type Button}}">
<ap:DynamicStyle.DerivedStyle>
<Style TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=FirstButtonWarning}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="{DynamicResource WarningBackground}"/>
<Setter Property="Foreground" Value="{DynamicResource WarningForeground}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</ap:DynamicStyle.DerivedStyle>
<TextBlock Text="Button that changes background and foreground when warning is active"/>
</Button>