2010-08-24 2 views
1

В: Почему мой пользовательский TextBox UserControl с использованием MultiBinding и IMultiValueConverter получает свой метод Convert(), вызываемый только один раз (во время instanciation)?MultiBinding и IMultiValueConverter Convert(), вызываемый только один раз

Я определил UserControl, который требует MultiBinding и IMultiValueConverter для того, чтобы изменить свое поведение/презентацию на 2 indenpendant DependencyProperty.

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

UserControl:

<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> 

При выполнении приложения, то все элементы управления UserControl правильно инстанциирован. Однако метод IMultiValueConverter.Convert() получил название только один раз.

Использование простой Binding + IValueConverter с постоянной ConvertParameter работал большой: Convert() метод преобразователя был бы дозвонились Каждый раз, когда TextBox содержится внутри UserControl была его свойство Текст изменен.

Дизайн изменился, и мне пришлось прибегнуть к помощи MultiBinding + IMultiValueConverter, и теперь метод Convert() только вызывается один раз, и TextBox.Text свойство никогда не обновляется на LostFocus() события.

Что дает?

MultiValueConverter определяется ниже. Я просто завершаю IMultiValueConverter на IValueConverter для повторного использования существующего кода.

[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

+0

Никакого исключения вообще! Похоже, что привязка работает нормально, но только при instanciation. –

ответ

0

Похоже, что у вас есть некоторые противоречивые ожидания относительно поведения обновления Binding и TextBox. Единственная причина, по которой Convert будет вызываться несколько раз, - это если значения Digits или Value меняются несколько раз, и в вашем опубликованном коде нет ничего, чтобы указать, что произойдет. Изменения в TextBox.Text не вызовут вызовы Convert, но вместо этого следует называть ConvertBack при каждом изменении + LostFocus. Вы видите, что когда вы запускаете свой код?

Вам также необходимо вернуть два значения, а не одно из них, из вашего метода ConvertBack, чтобы поставлять оба Bindings, используемых в MultiBinding со значениями.

+0

Вы правы. Мое понимание заключается в том, что традиционное Binding вносит любые изменения в свойство свойства Text связать DependencyProperty (в данном случае Value). После обновления значения вызывается метод Convert() (который делает мои пользовательские формы и другие вещи удалены для простоты в приведенном выше примере). - Тем не менее, MultiBinding, хотя он обновляет Value, не похоже, что он вызывает метод Convert(). Например, если привязка 2way была как-то сломана ... Я добавил код для обновления Value (и вместо этого использовал привязку OneWay), и теперь все в порядке, спасибо! –

Смежные вопросы