ComboBox - 从两个属性中选择对象

时间:2012-01-23 02:00:52

标签: c# wpf xaml data-binding combobox

我希望我的用户能够从WPF中的ComboBox中选择一个客户端(自定义对象)。 ComboBox将按FirstName(字符串)和LastName(字符串)显示所有客户端。

所以基本上我的ViewModel公开了一个客户端,它是用户将做出的选择,以及用于填充ComboBox的所有客户端的列表。 ComboBox的声明如下:

<ComboBox Grid.Row="3" Grid.Column="1" Text="{Binding Client}" ItemsSource="{Binding Clients}" IsEditable="True">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding StringFormat="{}{0} {1}">
                        <Binding Path="FirstName"/>
                        <Binding Path="LastName"/>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

当然,这不起作用,因为Text属性显示原始客户端(显示类型名称),如果用户键入名称,则无法将其转换为客户端。这似乎是一个非常简单的事情,通过在线搜索我似乎找到了几十个不同的解决方案:创建一个包装格式正确的名称,使用值转换器,使用数据模板...我不熟悉所有那些WPF技术,所以请帮我找出最好的(希望简单!)解决方案。

谢谢!

4 个答案:

答案 0 :(得分:3)

甚至有一种更简单的方法可以做到这一点。就像你说的,XAML绑定到对象的typename,这来自ToString()方法。这允许您覆盖方法并返回所需的格式,而无需复杂的多重绑定。

protected override ToString()
{
   return String.Format("{0} {1}", FirstName, LastName);
}

也可能是您使用Text属性错误而且您需要SelectedItem?

答案 1 :(得分:2)

你能尝试这样的事吗?

<!-- Example assumes DataContext of ComboBox is MasterViewModel below -->
<ComboBox Grid.Row="3" Grid.Column="1" ItemsSource="{Binding Clients}" IsEditable="True">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text={Binding FirstName} Margin="0,0,10,0"/>
                <TextBlock Text={Binding LastName}/>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

然后直接绑定到viewmodel属性

public class ClientViewModel: INotifyPropertyChanged
{
    public event EventHandler<PropertyChangedEventArgs> PropertyChanged; 

    private string firstName;
    private string lastName;

    public string FirstName
    {
        get { return this.firstName; }
        set 
        {
            this.firstName = value; // Dont forget to raise PropertyChanged!
        }
    }

    public string LastName
    {
        get { return this.firstName; }
        set 
        {
            this.lastName = value;
        }
    }
}

在您的MasterViewModel中公开IEnumerable<ClientViewModel>

public class MasterViewModel : INotifyPropertyChanged
{
    private IEnumerable<ClientViewModel> _clients = new ClientViewModel[] 
    {
        new ClientViewModel() { FirstName = "Dave", LastName = "Cameron" }, 
        new ClientViewModel() { FirstName = "Ed", LastName = "Miliband" }, 
    }
    public IEnumerable<ClientViewModel> Clients
    {
        get { return _clients; } 
    } 
}

DataTemplates的强大功能意味着您可以以您喜欢的方式呈现您的数据。在DataTemplate和多个文本框中使用StackPanel或Grid是最好的方法。

祝你好运

答案 2 :(得分:1)

我认为最简单的方法是向Client对象添加自定义属性。所以客户最终会像这样。请注意,Client对象必须在某个方面实现INotifyPropertyChanged,以便绑定基础结构能够接收更改。

public class Client : INotifyPropertyChanged
{
   //other fields/properies
   private string firstName;
   private string lastName;

   public string FirstName
   {
      get { return this.firstName; }
      set 
      {
         this.firstName = value;
         this.FirePropertyChanged("FirstName");
         this.FirePropertyChanged("DisplayName");
      }
   }

   public string LastName
   {
      get { return this.firstName; }
      set 
      {
         this.lastName = value;
         this.FirePropertyChanged("LastName");
         this.FirePropertyChanged("DisplayName");
      }
   }

   public string DisplayName
   {
      get 
      {
          return string.Format("{0} {1}", this.firstName, this.lastName);
      }
   }

   protected void FirePropertyChanged(string propertyName)
   {
      if (this.PropertyChanged != null)
         this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
}

然后你只有一个非常简单的ComboBox声明指向新的DisplayName属性:

编辑:

不使用Text属性,而是使用带有双向绑定的SelectedItem属性将其与ViewModel匹配。

<ComboBox Grid.Row="3" Grid.Column="1" SelectedItem="{Binding Client, Mode=TwoWay" ItemsSource="{Binding Clients}" DisplayMemberPath="DisplayName" />

答案 3 :(得分:1)

这应该是开箱即用的,但你似乎没有绑定组合的选定项目。

<ComboBox Grid.Row="3" Grid.Column="1" IsEditable="True"
          ItemsSource="{Binding Clients}"
          SelectedItem="{Binding Client}" >

我不清楚为什么你的编辑可以编辑。您是说用户可以键入要选择的名字/姓氏?在这种情况下,你需要转换器。