Вероятно, есть много лучших способов решения этой проблемы, но я попытался обойти две проблемы, которые у вас были с вашим решением. Небольшой пример проекта с этим можно скачать здесь .
1.Это только добавляет функциональность кнопкам и ничего больше.
Флаг IsAdvanced может (должен быть в состоянии
к) быть добавленным к любому визуальному элементу.
Добавление присоединенного свойства, которое заставляет все дочерние элементы наследовать значение, к самому верхнему контейнеру может исправить это.
2. Он заменяет / переопределяет стили, которые в противном случае были бы на
кнопка.
У Bea Stollnitz есть хорошая статья в блоге о слиянии стилей здесь .
У него есть метод расширения для стиля под названием Merge, который можно использовать.
Звучит довольно прямо, но следующие проблемы сделали код более сложным.
1. Элементы Visual не имеют стиля, когда свойство Attached наследуется. Обязательное загруженное событие.
2. Стиль не может быть изменен, когда он используется. Требуется метод копирования для стиля.
Итак, мы хотим, чтобы этот стиль был объединен с активным стилем для всех дочерних элементов в родительском контейнере.
<Style x:Key="IsAdvancedStyle">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding (library:MyLibraryControl.IsAdvanced), RelativeSource={RelativeSource Mode=Self}}" Value="True" />
<Condition Binding="{Binding IsChecked, ElementName=isAdvanced}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Control.Visibility" Value="Collapsed" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
Если корневым контейнером является StackPanel, мы добавляем это. Стиль IsAdvancedStyle будет затем унаследован всеми дочерними элементами и объединен с активным стилем.
<StackPanel local:StyleChildsBehavior.StyleChilds="{StaticResource IsAdvancedStyle}">
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);
}
}