Multibinding не работает на TextBox.Text
У меня есть MultiBinding, который не работает на TextBox.Text. У меня есть тот же код, который правильно привязывается к значению расширенного набора инструментов WPF IntegerUpDown.
Он проходит через IMultiValueConverter, который принимает связанный POCO и список, частью которого он является (он отображает порядок элемента в списке)
Вот код:
<!--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>
Вот результат:
Я не верю, что это актуально, но на всякий случай вот класс, который выполняет преобразование:
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
}
2 ответа
Преобразователь должен возвращать тип, который ожидает свойство. Причина в том, что при регулярном использовании свойств (т.е. без Binding
), свойства могут иметь преобразователи типов, которые преобразуют из одного типа (или более) в тип, требуемый свойством. Например, когда вы пишете:
<ColumnDefinition Width="Auto"/>
есть конвертер, который преобразует строку "Авто" в:
new GridLength(1, GridUnitType.Auto)
При использовании привязки этот механизм обходится, поскольку преобразователь должен возвращать правильный тип.
Итак, чтобы исправить вашу проблему, при возврате вашего конвертера:
return (lb.Items.IndexOf(trip) + 1).ToString();
Это должно исправить TextBox
,
Теперь для IntegerUpDown
, Похоже, что на самом деле ожидает получить int
и возвращение строки сломает ее. Итак, еще раз измените возврат конвертера:
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()));
}
Привязка не будет работать, потому что listTrips
не изменяется при изменении выбранного значения в списке. То, что меняется, это listTrips.SelectedItem
так что вы должны связать это:
<Binding Path="SelectedItem" ElementName="listTrips"/>
На самом деле, мне интересно, почему это работает для первого примера.