Ответ 1
Наконец, выяснилось решение для DynamicResouce
для Style.BasedOn
с помощью AttachedDependencyProperty
.
Вот исправление для ItemsControl.ItemContainerStyle
(можно легко изменить, чтобы изменить FrameworkElement.Style
)
public class DynamicContainerStyle
{
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(DynamicContainerStyle), new UIPropertyMetadata(DynamicContainerStyle.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(DynamicContainerStyle), new UIPropertyMetadata(DynamicContainerStyle.StylesChanged));
private static void StylesChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
if (!typeof(System.Windows.Controls.ItemsControl).IsAssignableFrom(target.GetType()))
throw new InvalidCastException("Target must be ItemsControl");
var Element = (System.Windows.Controls.ItemsControl)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.ItemContainerStyle = 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 DynamicContainerStyle class lives -->
<MenuItem Header="Recent"
ItemsSource="{Binding Path=RecentFiles}"
IsEnabled="{Binding RelativeSource={RelativeSource Self}, Path=HasItems}"
ap:DynamicContainerStyle.BaseStyle="{DynamicResource {x:Type MenuItem}}">
<ap:DynamicContainerStyle.DerivedStyle>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="RecentFile_Clicked"/>
</Style>
</ap:DynamicContainerStyle.DerivedStyle>
<MenuItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
Вот модифицированная версия, которая вместо FrameworkElement.Style
устанавливает в моем ответе на другой пост:
Настройка локального неявного стиля, отличного от стиля темы/альтернативы DynamicResource BasedOnn