使用带有ResourceDictionaries或MergedDictionaries的setter属性使用ItemsSource时的MenuItem样式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用带有ResourceDictionaries或MergedDictionaries的setter属性使用ItemsSource时的MenuItem样式相关的知识,希望对你有一定的参考价值。
我有一个上下文菜单,并且从加载了XamlReader.Load()的ResourceDictionary中正确设置样式。我正在使用的样式键是一个DynamicResource,我称之为styleBanner。
在这个上下文菜单中,我有一个名为Skins的菜单项,它也可以使用上面的动态资源styleBanner保存。但是这个菜单项的子菜单项数据绑定到数据上下文View Model中的ItemsSource,这也正常工作。
我的麻烦是子菜单项没有正确设置样式。
这是什么工作,但没有得到风格:
<Window.ContextMenu>
<ContextMenu DataContext="TimersHostViewModel" Name="TimersHostContextMenu" Style="{DynamicResource styleBanner}">
<MenuItem Name="Skins" Header="Skins" ItemsSource="{Binding Source={StaticResource TimersHostViewModel}, Path=Skins}" Style="{DynamicResource styleBanner}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=SkinName}"/>
<Setter Property="Command" Value="{Binding Source={StaticResource TimersHostViewModel}, Path=TimersHostContextMenuClickCommand}"/>
<Setter Property="CommandParameter" Value="{Binding Path=SkinName}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</ContextMenu>
</Window.ContextMenu>
所以这是我尝试过的一件事,我尝试添加以下行:
<Setter Property="Style" Value={DynamicResource styleBanner}"/>
像这样:
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=SkinName}"/>
<Setter Property="Style" Value="{DynamicResource styleBanner}"/>
<Setter Property="Command" Value="{Binding Source={StaticResource TimersHostViewModel}, Path=TimersHostContextMenuClickCommand}"/>
<Setter Property="CommandParameter" Value="{Binding Path=SkinName}"/>
</Style>
我在尝试时遇到异常:System.ArgumentException {“不允许Style对象影响它所适用的对象的Style属性。”}
所以我试着这个改变上面添加的行如下:
<Setter Property="Template" Value="{DynamicResource styleBanner}"/>
然后我得到一个不同的异常:System.InvalidCastException {“无法将'System.Windows.Style'类型的对象强制转换为'System.Windows.FrameworkTemplate'。”}
那么这样做的正确方法是什么?我已经在互联网和Stackoverflow上搜索了一下,没有任何线索。
编辑:好的我看到使用以下内容现在可用于获取子菜单项上的样式集:
<Setter Property="ItemContainerStyle" Value="{DynamicResource styleBanner}"/>
但由于某种原因,styleBanner背景不用于子菜单项。
我应该从我的ResourceDictionary发布了styleBanner,所以这里是:
<!-- Banner Style -->
<Style x:Key="styleBanner">
<Setter Property="StackPanel.Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="DarkGray" Offset="0.1" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="TextBlock.Foreground" Value="White" />
<Setter Property="TextBlock.FontFamily" Value="TR2N" />
</Style>
以下是我现在对上下文菜单的看法:
<Window.ContextMenu>
<ContextMenu DataContext="TimersHostViewModel" Name="TimersHostContextMenu" Style="{DynamicResource styleBanner}">
<MenuItem Name="Skins" Header="Skins" ItemsSource="{Binding Source={StaticResource TimersHostViewModel}, Path=Skins}" Style="{DynamicResource styleBanner}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=SkinName}"/>
<Setter Property="Command" Value="{Binding Source={StaticResource TimersHostViewModel}, Path=TimersHostContextMenuClickCommand}"/>
<Setter Property="CommandParameter" Value="{Binding Path=SkinName}"/>
<Setter Property="ItemContainerStyle" Value="{DynamicResource styleBanner}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</ContextMenu>
</Window.ContextMenu>
这是一张显示我得到的风格差异的图片:
因此,您可以看到应用了字体和字体颜色,但是使用ResourceDictionary中定义的渐变画笔的styleBanner背景则不是。
实际上如果仔细观察我玩了一个小技巧,上面的ResourceDictionary中的styleBanner是从BlackSkin.xaml ResourceDictionary发布的,它的渐变背景应该是深灰色,但屏幕截图显示的是蓝色背景,因为我有一个BlueSkin.xaml ResourceDictionary,但它们都很相似,并且都具有相同的行为,所以这里是BlueSkin.xaml ResourceDictionary的styleBanner,为了完整性:
<!-- Banner Style -->
<Style x:Key="styleBanner">
<Setter Property="StackPanel.Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0.25" EndPoint="1,0.5">
<GradientStop Color="#CC0088DD" Offset="0.3" />
<GradientStop Color="#3300FFFF" Offset="0.85" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="TextBlock.Foreground" Value="Yellow" />
<Setter Property="TextBlock.FontFamily" Value="Comic Sans MS" />
</Style>
您无法在Style中设置Style属性。
将StyleBanner设置为样式中的ItemContainerStyle
,例如ContextMenuStyle
例如。让我们将您的样式名称命名为ContextMenuStyle,并将其ItemContainer样式设置为StyleBanner
<Style x:Key="ContextMenuStyle" TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=SkinName}"/>
<Setter Property="Command" Value="{Binding Source={StaticResource TimersHostViewModel}, Path=TimersHostContextMenuClickCommand}"/>
<Setter Property="CommandParameter" Value="{Binding Path=SkinName}"/>
<Setter Property="ItemContainerStyle" Value="{DynamicResource styleBanner}"/>
</Style>
现在,您可以在上下文菜单中指定以下样式:
<ContextMenu.Style>
<StaticResource ResourceKey="ContextMenuStyle"></StaticResource>
</ContextMenu.Style>
希望你能得到这个想法......决定哪个属于style并且属于ContextMenuStyle并为控件设置Style
,你可以在样式中设置ContextMenuStyle
。您甚至可以在ContextMenuStyle
中嵌套styleBanner
,这将适用于子菜单
编辑:
你是对的,背景不会被转移到子菜单项。在这种情况下,现在剩下的唯一选择是使用背景定义ControlTemplate,尝试以下方法:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border >
<Border.Background>
<LinearGradientBrush StartPoint="0,0.25" EndPoint="1,0.5">
<GradientStop Color="#CC0088DD" Offset="0.3" />
<GradientStop Color="#3300FFFF" Offset="0.85" />
</LinearGradientBrush>
</Border.Background>
<Button Content="{Binding Path=SkinName}" Command="{Binding Source={StaticResource TimersHostViewModel}, Path=TimersHostContextMenuClickCommand}"
CommandParameter="{Binding Path=SkinName}"
Foreground="Yellow" FontFamily="Comic Sans MS"></Button>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
您可以使用“BasedOn”属性:
<MenuItem.ItemContainerStyle>
<Style BasedOn="{StaticResource ISAMenu}" TargetType="MenuItem">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}, Path=DataContext.ChangeLanguageCommand}" />
<Setter Property="CommandParameter" Value="{Binding}" />
</Style>
</MenuItem.ItemContainerStyle>
然后在你的App.xaml中引用一个字典
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/ResourceDictionaries/NavBarMenu.xaml" />
</ResourceDictionary.MergedDictionaries>
最后在NavBar Menu.xaml中
<Style x:Key="ISAMenu" TargetType="{x:Type MenuItem}">
这是一个老问题,但我花了几个小时找出另一个干净的解决方案,所以我希望它可以帮助别人。
以上是关于使用带有ResourceDictionaries或MergedDictionaries的setter属性使用ItemsSource时的MenuItem样式的主要内容,如果未能解决你的问题,请参考以下文章
使用 SharedResourceDictionary 时的内存泄漏
在 ResourceDictionary 中交换 DynamicResource