2012-01-23 53 views
1

我希望我的用户能够从WPF中的ComboBox中选择一个客户端(自定义对象)。 ComboBox将通过他们的FirstName(字符串)和LastName(字符串)显示所有客户端。组合框 - 从两个属性中选择对象

所以基本上我的ViewModel公开了一个单一的客户端,这是用户将做出的选择,以及用于填充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> 

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

谢谢!

回答

3

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

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

也许这也就是你正在使用的Text属性错了,你需要的SelectedItem?

+0

是的,但如果您想做更复杂的事情,它将无济于事。例如,粗体的名字,正常的姓氏。为此,你需要数据模型 –

+0

@ Dr.AndrewBurnett-Thompson Aah,这是真的,没有想过这个。 –

+0

我还为它+1了。简单往往被忽视;) –

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" /> 
+0

谢谢。这个问题是,当我从列表中选择一个客户端时,我得到:“System.Windows.Data错误:8:无法将值从目标保存回源代码(...)类型为'System.String'的对象无法转换为类型'[MyAppNamespace] .Client'“。 – Asik

+0

啊,我看是什么问题...假设“客户”属性的类型为“客户”的,看到我的编辑... –

+0

我+1了这个项目的FirePropertyChanged,这是我从我的答案为简洁起见省略 –

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> 

然后直接在您的MasterViewModel的IEnumerable<ClientViewModel>绑定到视图模型属性

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; 
     } 
    } 
} 

揭露这样

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和多个文本框是最好的方法。

问候函

相关问题