2010-02-21 17 views
16

是否可以使用值转换器,而无需事先将其定义为资源?使用WPF中的值转换器,无需先将其定义为资源

现在我有

<Window.Resources> 
    <local:TrivialFormatter x:Key="trivialFormatter" /> 
</Window.Resources> 

<Button Width="{Binding Width, ElementName=textBox1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource trivialFormatter}}" Height="50"> 

岂不是可能的,而不必申报Window.Resources的trivialFormatter资源,我可以直接从它指按钮的宽度绑定?喜欢的东西

Converter = {local:TrivialFormatter} 

感谢

回答

22

IValueConverter单型S的情况下(例如,它们不需要从当前绑定实例的任何状态)我用静止变流器,即:

Converter={x:Static SomeNamespace:SomeConverter.Instance} 

也有一个伟大的职位由博士WPF使用标记扩展使其更清晰地内联here

+0

标记扩展的好伎俩!然而,在你的第一个例子中,你不需要创建一个VC的静态实例,例如'{x:Static local:SomeConverter.Instance}'? – itowlson

+0

这是一个非常好的建议。在创建自己的值转换器时,您应该始终希望让它们接受ConverterParameter而不是具有实例属性,以便您可以像这样使用单例实例。这比使用资源要容易得多。我通常打电话给我的东西像{x:Static Local:InvertedBooleanConverter.Default}或其他东西。 – Josh

+0

@ itowlson - 对实例是 - 我编辑了我的回复。 Thx为捕获。 – micahtan

2

我不知道的方式做到这一点,您将可以说明的方式,但我只是想这是一个样本,它的工作。在你的App.xaml.cs文件中,你可以创建一个使用反射来加载转换器的方法。

private void Application_Startup(object sender, StartupEventArgs e) 
{ 
    LoadConverters(); 
} 

private void LoadConverters() 
{ 
    foreach(var t in Assembly.GetExecutingAssembly().GetTypes()) 
    { 
     if (t.GetInterfaces().Any(i => i.Name == "IValueConverter")) 
     { 
      Resources.Add(t.Name, Activator.CreateInstance(t)); 
     } 
    } 
} 

然后,你可以像这样使用转换器,我想我的一半。

<Button Width="{Binding Width, Converter={StaticResource TrivialFormatter}}" /> 

您提议的方法存在的问题是Xaml解析器不知道您的转换器的创建时间和数量。将其创建为资源只能确保一个实例。

+0

在一个相似的主题上,您可以创建一个标记扩展,它返回它的参数类型的一个实例。然后你可以写'Converter = {local:InstanceOf {x:Type local:TrivialFormatter}}'。但是,正如你注意到的那样,这将导致每个绑定都有一个单独的实例化,这可能是浪费的(特别是如果在ItemTemplate中用于大型ItemsControl)。 – itowlson

6

从技术上讲,我相信你能做到这一点,但XAML是如此的可怕,它会使“很多琐碎的资源”的方式看起来像简单和清晰的避风港通过比较:

<Button Height="50"> 
    <Button.Width> 
    <Binding Path="Width" ElementName="textBox1" UpdateSourceTrigger="PropertyChanged"> 
     <Binding.Converter> 
     <local:TrivialFormatter /> 
     </Binding.Converter> 
    </Binding> 
    </Button.Width> 
</Button> 

我有没有测试过,因为即使阅读它使我的眼睛水...

+5

这也是一种完全有效的方式。但正如你所指出的那样,XAML的冗长就像盟约的方舟,仅仅看着它就会吞噬你的灵魂。 – Josh

+0

如果你想在转换器的特定实例上设置一些属性,比如''' – chviLadislav

5

我肯定会研究Micah的建议,其中涉及使用您的转换器的静态单例实例。但需要考虑的另一件事是,如果您使用像MVVM这样的独立表示模式,则通常可以通过在ViewModel中实现转换来避免对值转换器的需求。

有很多原因可能需要这样做。

首先,它是可测试的。您的单元测试可以确保无论从ViewModel出来什么都将由UI显示。你能想象测试是美元价值必须按照当前区域性的货币格式的要求,保留两位小数,必须使用等

的另一个原因是,在值转换器的异常会被作为可成为验证错误处理Silverlight中的屁股巨大的痛苦。即使您在绑定中将ValidatesOnExceptions设置为true,如果值转换器引发异常,Silverlight也会让它传播。但是,如果您使用ViewModel进行转换,则会将异常视为验证错误。

不利的一面是,你失去了一些通用价值转换器的“可重用性”。

相关问题