Multibinding not working on TextBox.Text

2019-08-14 14:41发布

问题:

I have a MultiBinding that is not working on TextBox.Text. I have the same code that is binding properly to Value of Extended WPF Toolkit's IntegerUpDown.

It is going through an IMultiValueConverter that takes the bound POCO and the listbox it is part of (it is displaying the order of the item in the listbox)

Here is the code:

<!--works-->
<wpf:IntegerUpDown ValueChanged="orderChanged" x:Name="tripOrder">
    <wpf:IntegerUpDown.Value>
        <MultiBinding Converter="{StaticResource listBoxIndexConverter}" Mode="OneWay">
            <Binding />
            <Binding ElementName="listTrips" />
        </MultiBinding>
    </wpf:IntegerUpDown.Value>
</wpf:IntegerUpDown>
<!--doesn't work-->
<TextBox x:Name="tripOrder2">
    <TextBox.Text>
        <MultiBinding Converter="{StaticResource listBoxIndexConverter}" Mode="OneWay">
            <Binding />
            <Binding ElementName="listTrips" />
        </MultiBinding>
    </TextBox.Text>
</TextBox>

Here is the result:

I don't believe it is relevant, but just in case, here is the class that performs the conversion:

    public class ListBoxIndexConverter : IMultiValueConverter
    {

    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var trip = values[0] as TripBase;

        if (trip == null)
        {
            return null;
        }

        var lb = values[1] as CheckListBox;
        if (lb == null)
        {
            return null;
        }

        //make it 1 based
        return lb.Items.IndexOf(trip) + 1;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

回答1:

The converter should return the type that the property expects. The reason is that in regular use of the properties (i.e. without Binding), the properties may have type converters that convert from one type (or more) to the type required by the property. For example, when you write:

<ColumnDefinition Width="Auto"/>

there's a converter that converts string "Auto" to:

new GridLength(1, GridUnitType.Auto)

When using binding, this mechanism is bypassed since the converter should return the right type.

So, to fix your issue, at the return of your converter:

return (lb.Items.IndexOf(trip) + 1).ToString();

This should fix the TextBox.

Now, for the IntegerUpDown. It sounds like it actually expects to receive an int and returning a string will break it. So, again, change the return of the converter:

if (targetType == typeof(int))
{
    return lb.Items.IndexOf(trip) + 1;
}
else if (targetType == typeof(string))
{
    return (lb.Items.IndexOf(trip) + 1).ToString();
}
else
{
    throw new NotImplementedException(String.Format("Can not convert to type {0}", targetType.ToString()));
}


回答2:

The binding is not going to work, because the listTrips is not changing when the list box's selected value changes. The thing that changes is listTrips.SelectedItem, so you should bind against it:

<Binding Path="SelectedItem" ElementName="listTrips"/>

Actually, I wonder why it works for the first example.