我希望我的用户能够从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技术,所以请帮我找出最好的(希望简单!)解决方案。
谢谢!
答案 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}" >
我不清楚为什么你的编辑可以编辑。您是说用户可以键入要选择的名字/姓氏?在这种情况下,你需要转换器。