MultiBinding и IMultiValueConverter Convert () вызывается только один раз - PullRequest
2 голосов
/ 24 августа 2010

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

Я определил UserControl, который требуетMultiBinding и IMultiValueConverter, чтобы изменить его поведение / представление после 2-х независимых 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>

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

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

Дизайн изменяется, и мне пришлось прибегнуть к использованию 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) };
    }
}

1 Ответ

0 голосов
/ 25 августа 2010

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

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

...