如何为ConverterParameters启用动态蒙皮

时间:2012-02-02 07:52:27

标签: wpf resources skinning staticresource dynamicresource

当某些需要修改皮肤的项目不支持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。

在对此进行了一些研究后,特别是以下文章

How to assign wpf resources to other resource tags

Skinning using a color as staticresource for another color

Aliasing resources

我们认为我们现在需要做的是使用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行... 在这种情况下,传递给转换器的参数是Thickness SomeRandomResource。

所有这些都令人困惑,让我们觉得我们正在彻底咆哮错误的树。那么我们哪里出错了?

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

任何指针都非常感激。

1 个答案:

答案 0 :(得分:0)

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