可能有很多更好的方法来解决这个问题,但我试图解决你的解决方案中的两个问题。这个小样本项目可以在这里下载。
1.它只为按钮添加功能,而不是其他功能。该
IsAdvanced标志可以(应该可以
to)被添加到任何视觉元素。
添加一个附加属性,使所有子级继承该值,到最顶层的容器可以解决这个问题。
2.它取代/覆盖否则将会出现的样式
按钮。
Bea Stollnitz有一篇关于合并样式的博客文章。
它有一个名为Merge的Style的扩展方法,可以使用它。
听起来非常直接,但以下问题使代码更复杂。
1.继承附加属性时,Visual元素没有样式。必需的已加载事件。
2.使用时不能修改样式。要求样式的复制方法。
因此,我们希望将此样式与父容器中所有子项的活动样式合并。
如果根容器是StackPanel,那么我们添加它。然后,样式IsAdvancedStyle将由所有子项继承并与活动Style合并。
StyleChildsBehavior.cs
public class StyleChildsBehavior
{
public static readonly DependencyProperty StyleChildsProperty =
DependencyProperty.RegisterAttached("StyleChilds",
typeof(Style),
typeof(StyleChildsBehavior),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.Inherits,
StyleChildsCallback));
public static void SetStyleChilds(DependencyObject element, Style value)
{
element.SetValue(StyleChildsProperty, value);
}
public static Style GetStyleChilds(DependencyObject element)
{
return (Style)element.GetValue(StyleChildsProperty);
}
private static void StyleChildsCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(d) == true)
{
return;
}
Style isAdvancedStyle = e.NewValue as Style;
if (isAdvancedStyle != null)
{
FrameworkElement element = d as FrameworkElement;
if (element != null)
{
if (element.IsLoaded == false)
{
RoutedEventHandler loadedEventHandler = null;
loadedEventHandler = new RoutedEventHandler(delegate
{
element.Loaded -= loadedEventHandler;
MergeStyles(element, isAdvancedStyle);
});
element.Loaded += loadedEventHandler;
}
else
{
MergeStyles(element, isAdvancedStyle);
}
}
}
}
private static void MergeStyles(FrameworkElement element, Style isAdvancedStyle)
{
if (element != null)
{
Style advancedStyle = GetStyleCopy(isAdvancedStyle);
advancedStyle.Merge(element.Style);
element.Style = advancedStyle;
}
}
private static Style GetStyleCopy(Style style)
{
string savedStyle = XamlWriter.Save(style);
using (MemoryStream memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(savedStyle)))
{
ParserContext parserContext = new ParserContext();
parserContext.XmlnsDictionary.Add("library", "clr-namespace:HideAll;assembly=HideAll");
return XamlReader.Load(memoryStream, parserContext) as Style;
}
}
}
在此之后,IsAdvancedStyle将合并到StackPanel的所有子项中,这适用于在运行时添加的子项。
从博客链接修改了合并扩展方法。
public static void Merge(this Style style1, Style style2)
{
if (style1 == null || style2 == null)
{
return;
}
if (style1.TargetType.IsAssignableFrom(style2.TargetType))
{
style1.TargetType = style2.TargetType;
}
if (style2.BasedOn != null)
{
Merge(style1, style2.BasedOn);
}
foreach (SetterBase currentSetter in style2.Setters)
{
style1.Setters.Add(currentSetter);
}
foreach (TriggerBase currentTrigger in style2.Triggers)
{
style1.Triggers.Add(currentTrigger);
}
}