2010-08-24 88 views
1

问:为什么使用MultiBinding和IMultiValueConverter的自定义TextBox UserControl只获得一次调用的Convert()方法(在实例化期间)?MultiBinding和IMultiValueConverter Convert()仅调用一次

我已经定义了需要MultiBindingIMultiValueConverter为了在2 indenpendant DependencyProperty改变其行为/演示一个用户控件。

<proj:MyControl Value="10" Digits="1" /> 

用户控件:

<UserControl x:Class="MyControl" 
      x:Name="uc" 
      ...> 

    <UserControl.Resources> 
     <conv:DecimalToStringMultiConverter x:Key="DecToString" /> 
    </UserControl.Resources> 

    [...] 

    <Grid> 
     <ctrl:VTextBox x:Name="vTb" Grid.Column="0" Margin="0,0,2,0"> 
      <ctrl:VTextBox.Text> 
       <MultiBinding Converter="{StaticResource DecToString}" UpdateSourceTrigger="LostFocus" Mode="TwoWay"> 
        <Binding ElementName="uc" Path="Value" Mode="TwoWay" /> 
        <Binding ElementName="uc" Path="Digits" Mode="TwoWay" /> 
       </MultiBinding> 
      </ctrl:VTextBox.Text> 
     </ctrl:VTextBox> 
    </Grid> 
</UserControl> 

当执行应用程序时,用户控件都正确地实例化。然而,IMultiValueConverter.Convert()方法被称为只有一次

使用一个简单的Binding + IValueConverter以恒定ConvertParameter伟大的工作:转换器的Convert()方法将被调用每次包含UserControlTextBox有它的Text属性更改。

设计改变了,我不得不求助于使用MultiBinding + IMultiValueConverter,现在Convert()方法只被调用一次,TextBox.Text属性从未于LostFocus()事件更新。

什么给?

MultiValueConverter的定义如下。我只是在IValueConverter上包装IMultiValueConverter以重用现有的代码。

[ValueConversion(/*sourceType*/ typeof(Decimal), /*targetType*/ typeof(string))] 
public class DecimalToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return "0.00"; 

     int? digits = parameter as int?; 

     if(digits == null) 
      digits = 2; 

     NumberFormatInfo nfi = (NumberFormatInfo) CultureInfo.InvariantCulture.NumberFormat.Clone(); 
     nfi.NumberGroupSeparator = " "; 
     nfi.CurrencyDecimalSeparator = "."; 
     nfi.NumberDecimalDigits = (int)digits; 

     return ((decimal)value).ToString("n", nfi); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return 0.00m; 

     decimal d; 

     return decimal.TryParse((string)value, out d) ? d : 0.00m; 
    } 
} 

[ValueConversion(/*sourceType*/ typeof(Decimal), /*targetType*/ typeof(string))] 
public class DecimalToStringMultiConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     DecimalToStringConverter conv = new DecimalToStringConverter(); 
     return conv.Convert(values[0], targetType, values.Length > 1 ? values[1] : null, culture); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     DecimalToStringConverter conv = new DecimalToStringConverter(); 
     return new[] { conv.ConvertBack(value, targetTypes[0], null, culture) }; 
    } 
} 
+0

当你在调试器中运行它时,你会在输出窗口中看到异常吗? – Jay 2010-08-24 19:44:48

+0

没有任何异常!绑定似乎工作正常,但只在instanciation。 – 2010-08-24 20:18:01

回答

0

看起来好像你对Binding和TextBox的更新行为有一些矛盾的期望。多次调用转换的唯一原因是数字或值的值多次更改,并且您的发布代码中没有任何内容表明会发生此情况。对TextBox.Text的更改不会导致调用转换,而应该在每次更改+ LostFocus时调用ConvertBack。你在运行代码时看到了吗?

您还需要从您的ConvertBack方法返回两个值,而不是现在那里的值,以便为MultiBinding中使用的绑定提供值。

+0

你说得对。我的理解是,传统的Binding对Text属性进行任何更改都会更新绑定的DependencyProperty(在本例中为Value)。在更新Value之后,Convert()方法被调用(为了简化,我在上面的例子中删除了我的自定义格式化和其他内容)。 - 但是,MultiBinding虽然更新了Value,但看起来并不像触发Convert()方法。就像2way绑定被破坏了一样......我添加了一些代码隐藏来更新Value(并使用OneWay绑定)而现在一切都很好,谢谢! – 2010-08-26 15:31:06