使用转换器绑定ComboBox Text属性

问题描述 投票:2回答:3

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

视图模型

  • 提供ObservableCollection<T>;此集合包含用户可以选择的项目列表。
  • 提供表示所选项目的T类型的属性。

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

我有一个转换器可以将T类型的项目转换为string,反之亦然。

视图

我的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下拉列表中的项目。显示在TextBoxComboBox中的所选项目未正确显示;不使用我的转换器,而是使用ToString方法。

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

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

这解决了显示问题,但现在我在转换器Type.FullName方法中获得了T的ConvertBack - 当然不能转换。

摘要

我希望用户能够从集合中选择一个项目,允许他通过输入字符串表示来添加新项目。集合中的项目应使用转换器在字符串和对象表示之间进行转换。转换应在下拉列表和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执行此操作?

wpf text binding combobox converter
3个回答
0
投票

我已经尝试过了,但它并不合乎逻辑,因为转换器也应该得到集合的实例(在键入时添加内容)并且我认为尝试这样做会看起来很脏。你试过逆转逻辑吗?这是一个有效的例子,但我不知道它是否完全符合你的需要。

<ComboBox Height="23" HorizontalAlignment="Left" Name="comboBox1" 
          VerticalAlignment="Top" Width="163"
          ItemsSource="{Binding}"
          DisplayMemberPath="Name" IsEditable="True"
          TextBoxBase.TextChanged="comboBox1_TextChanged"/>

代码背后:

ObservableCollection<Type> types = new ObservableCollection<Type>( );

public MainWindow( )
{
  InitializeComponent( );
  types.Add( typeof( string ) );
  types.Add( typeof( bool ) );
  types.Add( typeof( int ) );
  types.Add( typeof( decimal ) );
  types.Add( typeof( double ) );
  comboBox1.DataContext = types;
}

private void comboBox1_TextChanged( object sender , TextChangedEventArgs e )
{
  if ( !( comboBox1.SelectedValue == null && !String.IsNullOrEmpty( comboBox1.Text ) ) ) { return; }
  var type = Type.GetType( String.Format( "System.{0}" , comboBox1.Text ) , false , true );
  if ( type != null && !types.Contains(type))
  {
    types.Add( type );
  }
}

现在尝试在ComboBox中输入类似'datetime'的内容。


0
投票

我现在使用不同的方法解决问题:

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

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

UpdateSourceTrigger=LostFocus部分用于防止不必要的更新。


0
投票

如果有人遇到相同的问题,并且不想应对要绑定的字符串属性。

您可以使用以下内容

<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属性,并且combobox表现得很好,可以显示枚举的字符串值表示。

HTH

© www.soinside.com 2019 - 2024. All rights reserved.