使用转换器绑定ComboBox文本属性

4

在以下场景中,我在使用 WPF ComboBox 时遇到了麻烦:

ViewModel

  • 提供一个 ObservableCollection<T>;该集合包含用户可以选择的项目列表。

  • 提供一个类型为 T 的属性,表示所选项目。

用户应该能够从 ObservableCollection<T> 中的现有项或通过键入字符串表示来添加新项。

我有一个可用于将类型为 T 的项转换为 string 和反之亦然的转换器。

View

我的 ComboBox 绑定到集合和所选项目属性:

<ComboBox ItemsSource="{Binding Path=MyObservableCollection}"
          SelectedItem="{Binding Path=MySelectedItem}"
          IsReadOnly="False" IsEditable="True"/>

数据模板用于正确显示项目:
<DataTemplate DataType="{x:Type T}">
    <TextBlock Text="{Binding Converter={StaticResource ResourceKey=MyConverter}}"/>
</DataTemplate>
问题

ComboBox下拉列表中使用转换器正确显示项目。但是在ComboBoxTextBox中显示的所选项不正确;它没有使用我的转换器,而是使用了ToString方法。

是否可以为Text属性指定转换器?我尝试使用以下代码:

<ComboBox ItemsSource="{Binding Path=MyObservableCollection}"
          SelectedItem="{Binding Path=MySelectedItem}"
          Text="{Binding Path=MySelectedItem, Converter={StaticResource ResourceKey=MyConverter}}"
          IsReadOnly="False" IsEditable="True"/>

这解决了显示问题,但现在我在转换器的ConvertBack方法中获取T的Type.FullName - 当然无法转换。 摘要 我希望用户能够从集合中选择项目,并允许他通过输入字符串表示来添加新项目。集合中的项目应使用转换器在字符串和对象表示之间进行转换。该转换应在ComboBox的下拉列表和文本框中均可完成。 编辑 以下是我的转换器代码 - 没有什么魔法,只有直接的转换:
public class MyConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return MyConverter.Convert(value as T);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return MyConverter.Convert(value as string);
    }

    public static string Convert(T key)
    {
        // Conversion from T to string.
    }

    public static T Convert(string key)
    {
        // Conversion from string to T.
    }

}

好的,现在我找到了符合我的需求的东西:

        <TextBox Text="{Binding Path=MySelectedItem, Converter={StaticResource ResourceKey=MyConverter}}"/>
        <ListBox ItemsSource="{Binding Path=MyObservableCollection}"
                 SelectedItem="{Binding Path=MySelectedItem, Converter={StaticResource ResourceKey=MyConverter}}"/>

这正好符合我的要求;我可以选择预定义的值,用户也可以自己添加值。ComboBox能够实现这个功能吗?

为什么不能转换回去?使用Type.GetType((string)value, true, true)和Activator(如果需要)来进行转换。 - Silvermind
你能给我们提供转换器代码吗? - Silvermind
@Silvermind 我添加了转换器代码。问题在于 type.GetType((string)value, true, true) 仍然需要值为实际值,但它实际上是包含 Type.FullNamestring - Korexio
2个回答

2

如果有人遇到同样的问题,且不想处理绑定到字符串属性的情况。

可以使用以下方法:

<ComboBox 
      ItemsSource="{Binding Path=MyObservableCollection}"
      Text="{Binding MySelectedItem, Converter={StaticResource DisplayConverter}}"
      SelectedValue="{Binding MySelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"                  
      >
<ComboBox.ItemTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding Converter={StaticResource DisplayConverter}}"/>
    </DataTemplate>
</ComboBox.ItemTemplate>

请注意绑定是在SelectedValue上完成的,而不是SelectedItem。 然后将显示转换器添加到Text和ItemTemplate属性中。

  • 在Text属性上,它将用于转换所选项的显示值。
  • 在ItemTemplate上,它将用于转换列表框内的显示值

我甚至使用这个片段来处理在xaml中定义的ObjectDataProvider中出现的Enum集合。 我的枚举具有DisplayString属性,组合框可以很好地显示枚举的字符串值表示。

希望对你有所帮助。


0

我现在采用了不同的方法来解决这个问题:

我的视图模型提供了一个可观察集合和一个字符串属性。该集合绑定到ComboBox的ItemsSource属性,所选项目绑定到字符串属性。

        <ComboBox
            ItemsSource="{Binding Path=MyCollection}" 
            Text="{Binding Path=MyProperty, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
            IsReadOnly="False" IsEditable="True"/>

UpdateSourceTrigger=LostFocus 部分用于避免不必要的更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接