1

当某些需要皮肤修改的项目不支持 DynamicResourceExtention 类型的值时,启用 WPF 应用程序动态皮肤的最佳方法是什么?特别是,我们的问题是 ConverterParameters 需要 StaticResourceExtentions。

这是我们使用 Visual Studio 2008 和 WPF 3.5 使用 ConverterParameters 的情况。

我们有一个自定义转换器,它接受一个值和一个参数并简单地返回他们的产品。非常简单,工作正常,我们将它用于各种任务,包括设置一些窗口元素大小。例如,传递“Source={x:Static SystemParameters.PrimaryScreenHeight}”的值和“0.1”的参数使我们能够将元素的高度设置为屏幕高度的 1/10。

  Height="{Binding Source={x:Static SystemParameters.PrimaryScreenHeight}, 
                   Converter={StaticResource PctConverter}, 
                   ConverterParameter=0.1}"

其中 PctConverter 是对我们自定义转换器的资源引用。那里没问题。

现在我们想通过提取 ConverterParameter 并将其放入单独的资源中动态地为应用程序设置皮肤。例如,我们可能希望元素高度在某些皮肤中为屏幕高度的 0.1,而在其他皮肤中为屏幕高度的 0.25。最初我们认为我们只需将 ConverterParameter 设置为 DynamicResource,但这不支持,因此我们必须使用 StaticResourceExtension 设置它,如下所示:

  Height="{Binding Source={x:Static SystemParameters.PrimaryScreenHeight}, 
           Converter={StaticResource PctConverter}, 
           ConverterParameter={StaticResource OurElementHeightParameter}}"

其中 OurElementHeightParameter 在单独的 ResourceDictionary(称为 MainResource.xaml)中定义如下:

<sys:Double x:Key="OurElementHeightParameter">0.1</sys:Double>

(其中命名空间定义为 xmlns:sys="clr-namespace:System;assembly=mscorlib"。)

就提取 CustomParameter 而言,这很好用,但它仍然无法让我们通过动态交换皮肤来更改 ConverterParameter。

在对此进行了更多研究之后,特别是以下文章

如何将 wpf 资源分配给其他资源标签

使用一种颜色作为另一种颜色的静态资源进行蒙皮

别名资源

我们认为我们现在需要做的是获取我们的 StaticResourceExtention 并使用资源别名在幕后动态设置它的值。

为了做到这一点,我们将之前的 OurElementHeightParameter 资源替换为以下两个资源

<sys:Double x:Key="SkinnedHeightRatio">0.1</sys:Double>
<StaticResourceExtension x:Key="OurElementHeightParameter" ResourceKey="SkinnedHeightRatio" />

效果很好,产生了相同的结果。

当一切正常时,我们认为将 SkinnedHeightRatio 资源放置在单独的 ResourceDictionary(称为 Skin.xaml)中并将其与原始 MainResource.xaml ResourceDictionary 合并是一件简单的事情,我们将拥有我们所追求的动态皮肤。

但是,一旦我们提取<sys:Single x:Key="SkinnedHeightRatio">0.1</sys:Single>到另一个 ResourceDictionary,我们就会遇到如下构建错误:

未知的构建错误,“索引超出范围。必须是非负数且小于集合的大小。

更奇怪的是,如果我们将上面的两个资源保存在同一个 ResourceDictionary 中,并通过在它们之间放置另一个随机资源来分隔它们,例如

<sys:Double x:Key="SkinnedHeightRatio">0.1</sys:Double>
<Thickness x:Key="SomeRandomResource" >5</Thickness>
<StaticResourceExtension x:Key="OurElementHeightParameter" ResourceKey="SkinnedHeightRatio" />

然后 OurElementHeightParameter 指向其正上方的 SomeRandomResource,而不是其 ResourceKey 属性 (SkinnedHeightRatio) 中指定的资源,后者仅在其上方 2 行...在这种情况下,传递给转换器的参数是厚度 SomeRandomResource。

一切都非常混乱,让我们认为我们完全找错了树。那么我们哪里错了?

如果有人需要重现该问题的应用程序的完整代码,我可以将其发布。

任何指针都非常感谢。

4

1 回答 1

0

创建一个多值转换器并为其绑定两个值可能更简单。

于 2012-07-12T10:51:24.117 回答