![]() |
1
141
我认为简单的答案是你不能做(至少在这个版本的WPF中)你想做的事情。 也就是说,对于任何特定的元素,只能应用一种样式。
但是,正如上面其他人所说,也许您可以使用
所以,这里的想法…如果你能以某种方式分离你想要设置的属性…根据要在其上设置多个样式的元素的继承层次结构…你可能有一个解决办法。
注:
有一件事需要特别注意。如果你改变
|
![]() |
2
40
比亚斯托尔尼茨 a good blog post 关于为此使用标记扩展名,请在标题“如何在WPF中设置多个样式?” 那个博客现在死了,所以我在这里转载这篇文章 WPF和Silverlight都提供了通过basedon属性从另一个样式派生样式的能力。此功能允许开发人员使用类似于类继承的层次结构来组织他们的样式。考虑以下样式:
使用此语法,使用RedButtonStyle的按钮将其Foreground属性设置为红色,其Margin属性设置为10。 这个功能在WPF中已经存在很长一段时间了,它在Silverlight3中是新的。 如果你想在一个元素上设置多个样式怎么办?WPF和Silverlight都没有现成的解决方案来解决这个问题。幸运的是,有一些方法可以在WPF中实现这种行为,我将在本文中讨论。 WPF和Silverlight使用标记扩展为属性提供需要某些逻辑才能获取的值。标记扩展可以通过在XAML中围绕它们的大括号很容易识别。例如,绑定标记扩展包含从数据源获取值并在发生更改时更新该值的逻辑;静态资源标记扩展包含从基于键的资源字典获取值的逻辑。幸运的是,WPF允许用户编写自己的自定义标记扩展。Silverlight中还没有此功能,因此此日志中的解决方案仅适用于WPF。 Others 编写了使用标记扩展合并两种样式的伟大解决方案。然而,我想要一个能够合并无限数量样式的解决方案,这有点棘手。 编写标记扩展是很简单的。第一步是创建一个从markup extension派生的类,并使用markupextensionReturnType属性指示您希望从标记扩展返回的值具有类型样式。
指定标记扩展的输入我们想给标记扩展的用户一个简单的方法来指定要合并的样式。用户可以通过两种方式指定标记扩展的输入。用户可以设置属性或将参数传递给构造函数。因为在这个场景中,用户需要能够指定无限数量的样式,所以我的第一个方法是创建一个使用params关键字获取任意数量字符串的构造函数:
我的目标是能够写出以下输入:
注意逗号分隔不同的样式键。不幸的是,自定义标记扩展不支持无限数量的构造函数参数,因此这种方法会导致编译错误。如果我事先知道要合并多少样式,我可以使用相同的XAML语法,让构造函数获取所需的字符串数:
作为解决方法,我决定让构造函数参数采用一个字符串,该字符串指定由空格分隔的样式名。语法也不错:
计算标记扩展的输出要计算标记扩展的输出,我们需要重写MarkupExtension中名为ProvideValue的方法。此方法返回的值将在标记扩展的目标中设置。 我首先为知道如何合并两个样式的样式创建一个扩展方法。此方法的代码非常简单:
根据上面的逻辑,第一个样式被修改为包含第二个样式的所有信息。如果有冲突(例如,两种样式都有一个相同属性的setter),则第二种样式获胜。注意,除了复制样式和触发器,我还考虑了targetType和basedon值以及第二种样式可能拥有的任何资源。对于合并样式的targetType,我使用了更派生的类型。如果第二个样式有basedon样式,我将递归地合并它的样式层次结构。如果它有资源,我将它们复制到第一个样式。如果使用staticresource引用这些资源,则在执行此合并代码之前静态解析这些资源,因此无需移动它们。我添加了这段代码以防使用动态资源。 上面显示的扩展方法启用以下语法:
如果在providevalue中有两种样式的实例,那么这种语法很有用。嗯,我不喜欢。我从构造函数中得到的只是这些样式的字符串键列表。如果构造函数参数中支持参数,我可以使用以下语法来获取实际的样式实例:
但这行不通。即使参数限制不存在,我们也可能遇到标记扩展的另一个限制,即我们必须使用属性元素语法而不是属性语法来指定静态资源,这既冗长又麻烦(我在 previous blog post )即使这两个限制都不存在,我还是宁愿只使用它们的名称来编写样式列表。对于每一个样式,读取它比使用静态资源要简短和简单。 解决方案是使用代码创建StaticResourceExtension。给定一个字符串类型的样式键和一个服务提供者,我可以使用StaticResourceExtension来检索实际的样式实例。语法如下:
现在我们有了编写providevalue方法所需的所有部分:
以下是使用多样式标记扩展的完整示例:
|
![]() |
3
30
但你可以从另一个扩展……看看basedon属性
|
![]() |
4
17
WPF/XAML本机不提供此功能,但它提供了可扩展性,允许您执行所需的操作。 我们遇到了同样的需求,最终创建了自己的XAML标记扩展(我们称之为“MergedStylesExtension”),允许我们从两个其他样式创建新样式(如果需要,可能会在一行中多次使用这些样式来继承更多的样式)。 由于wpf/xaml错误,我们需要使用属性元素语法来使用它,但除此之外,它似乎工作正常。例如。,
|
![]() |
5
3
这可以通过创建一个助手类来使用和包装样式。提到的复合样式 here 演示如何执行。有多种方法,但最简单的方法是:
希望有帮助。 |
![]() |
6
2
使用
Usege:
结果:
|
![]() |
7
1
如果不接触任何特定属性,则可以将所有基本属性和公共属性获取到目标类型为FrameworkElement的样式。然后,您可以为所需的每个目标类型创建特定的口味,而无需再次复制所有这些公共属性。 |
![]() |
8
1
如果通过使用样式选择器将此应用于项集合,您可能会得到类似的结果,我使用此方法处理了根据树中绑定的对象类型在TreeView项上使用不同样式时的类似问题。您可能需要稍微修改下面的类以适应您的特定方法,但希望这将使您开始学习。
你就这样应用这个 <TreeView> <TreeView.ItemContainerStyleSelector <myassembly:MyTreeStyleSelector DefaultStyle="{StaticResource DefaultItemStyle}" NewStyle="{StaticResource NewItemStyle}" /> </TreeView.ItemContainerStyleSelector> </TreeView> |
![]() |
9
1
有时您可以通过嵌套面板来实现这一点。假设你有一个改变前景的样式和另一个改变字体大小的样式,你可以将后一个应用到一个文本块上,并把它放在一个网格中,它的样式是第一个。这可能有帮助,在某些情况下可能是最简单的方法,尽管它不能解决所有问题。 |
![]() |
10
1
当重写SelectStyle时,可以通过如下反射获取GroupBy属性:
|
![]() |
11
0
如果您试图只对一个元素应用一个独特的样式 作为对基本样式的补充,有一种完全不同的方法可以做到这一点,对于可读和可维护的代码来说,imho要好得多。 每个元素都需要调整参数,这是非常常见的。仅仅为一个元素定义字典样式对于维护或理解来说是非常麻烦的。为了避免只为一次性的元素调整创建样式,请在此处阅读我自己的问题的答案: |
![]() |
Metallistener · 更改样式onPress事件反应本机 7 年前 |
![]() |
Guillaume · react中的动态样式 7 年前 |
![]() |
BrianM · 未加载带底漆样式的离子2 7 年前 |
![]() |
Wizeek · 是否可以将动态样式应用为角度中的字符串? 7 年前 |