在 WPF 中设置嵌套元素的样式
Posted
技术标签:
【中文标题】在 WPF 中设置嵌套元素的样式【英文标题】:Styling nested elements in WPF 【发布时间】:2010-10-14 13:19:40 【问题描述】:假设您有一个嵌套的元素结构,例如带有 MenuItems 的 ContextMenu:
<ContextMenu Style="StaticResource FooMenuStyle">
<MenuItem Style="StaticResource FooMenuItemStyle"/>
...
</ContextMenu>
您可以轻松地将样式或模板应用于 ContextMenu 或 MenuItem 元素。但是,如果 MenuItem 样式属于 Menu 样式,则将其添加到每个 MenuItem 元素中是非常麻烦和多余的。
有没有办法自动将这些应用到子元素?这样你就可以简单地写这个:
<ContextMenu Style="StaticResource FooMenuStyle">
<MenuItem/>
...
</ContextMenu>
如果 FooMenuStyle 可以设置包含 MenuItem 元素的样式,那就太好了,但这似乎是不可能的。
编辑:Menu 示例可能具有误导性,因为我不知道 ItemContainerStyle 并且其意图是提供通用解决方案。基于这两个答案,我提出了两种解决方案:一种是通用变体,一种是 ItemContainerStyle 等:
<Style x:Key="FooMenuItem" TargetType="x:Type MenuItem">
...
</Style>
<Style x:Key="FooMenu" TargetType="x:Type ContextMenu">
<!-- Variant for specific style attribute -->
<Setter Property="ItemContainerStyle"
Value="StaticResource FooMenuItem"/>
<!-- General variant -->
<Style.Resources>
<Style TargetType="x:Type MenuItem"
BasedOn="StaticResource FooMenuItem"/>
</Style.Resources>
</Style>
<ContextMenu Style="StaticResource FooMenu">
<MenuItem/>
</ContextMenu>
【问题讨论】:
【参考方案1】:只是为了完成原始答案,我认为在父级内部添加嵌套样式会更清楚:
<Style x:Key="WindowHeader" TargetType="DockPanel" >
<Setter Property="Background" Value="AntiqueWhite"></Setter>
<Style.Resources>
<Style TargetType="Image">
<Setter Property="Margin" Value="6"></Setter>
<Setter Property="Width" Value="36"></Setter>
<Setter Property="Height" Value="36"></Setter>
</Style>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"></Setter>
</Style>
</Style.Resources>
</Style>
【讨论】:
这是最合适的答案。在网络上没有任何地方可以罚款。你摇滚!谢谢。 谢谢,这个信息真的很难找到。 我使用此示例帮助我将样式应用于嵌套在工具提示中的所有文本块 - 设置最大宽度并强制换行,以便更好地格式化长消息。 这真的很有用。谢谢。 作为参考,如果有人需要针对特定类型,可以使用DynamicResource
属性来完成,如下所述:***.com/a/31045455【参考方案2】:
<ContextMenu>
<ContextMenu.Resources>
<Style TargetType="x:Type MenuItem">
<!--Setters-->
</Style>
</ContextMenu.Resources>
<MenuItem/>
<!--Other MenuItems-->
</ContextMenu>
样式将应用于 ContextMenu 中的所有 MenuItem 对象。
【讨论】:
我认为他的资源中已经有了样式,并希望将其应用于子项,而不是再次重新声明。 而且,使用ItemContainerStyle可以更清晰的表达出来。 您可以声明从以前的样式派生的新样式。【参考方案3】:<ContextMenu ItemContainerStyle="StaticResource FooMenuItemStyle">
<MenuItem/>
</ContextMenu>
【讨论】:
我认为我的菜单示例有点误导(因为我不知道 ItemContainerStyle),并且最初的意图是针对任意元素。但因为我实际上有一个菜单,所以这是要走的路。【参考方案4】:我完成此操作的方法是在全局资源字典中创建一个 keyed ResourceDictionary
inside,然后仅将其应用于父元素。
在 app.xaml 中:
<Application.Resources>
<ResourceDictionary>
...
<ResourceDictionary x:Key="menuChildrenStyles">
<Style TargetType="MenuItem">
<!--Setters-->
</Style>
</ResourceDictionary>
...
</ResourceDictionary>
</Application.Resources>
然后在您的其他 xaml 视图中:
<ContextMenu Resources="StaticResource menuChildrenStyles">
<MenuItem />
<MenuItem />
<MenuItem />
<MenuItem />
</ContextMenu>
这会将MenuItem
样式应用于父元素内的所有MenuItem
元素。
您还可以将其他样式添加到“menuChildrenStyles”字典中,例如TextBlock
等。
【讨论】:
以上是关于在 WPF 中设置嵌套元素的样式的主要内容,如果未能解决你的问题,请参考以下文章
WPF ContextMenu 和 MenuItem 无法在默认样式 WPF 中设置 OverridesDefaultStyle 属性