WPF:ComboBox显示数据而不是“(命名空间).(类名)”

11

我想在XAML中将我的ComboBox绑定到代码后台中的自定义对象List集合。

当前ComboBox为每个条目列出dpwpf.Contact,这是我的{namespace}.{classname}

我需要在XAML中放什么来告诉它如何列出,例如,姓和名字?

我知道这类似于{Binding Path=... Value=...},但我无法实现它。

XAML:

<Window x:Class="dpwpf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <StackPanel>
            <TextBlock Text="Select the contact:"/>
            <ComboBox Name="theContactList"/>
        </StackPanel>
    </StackPanel>
</Window>

后端代码:

namespace dpwpf
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            StoreDB db = new StoreDB();
            List<Contact> contacts = db.GetContacts()
            theContactList.ItemsSource = contacts.ToList();
        }
    }
}

答案:

<Window x:Class="dpwpf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    xmlns:local="clr-namespace:dpwpf">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Contact}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding LastName}"/>
                <TextBlock Text=" "/>
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>

    <StackPanel>
        <StackPanel Margin="10">
            <TextBlock Text="Contact Name:" Foreground="#555"/>
            <TextBox Name="theName"/>
        </StackPanel>
        <StackPanel>
            <TextBlock Text="Select the contact:"/>
            <ComboBox Name="theContactList"/>
        </StackPanel>
    </StackPanel>
</Window>

4个回答

10

您可以重写Contact类的ToString方法,或者在WPF中定义一个DataTemplate

xmlns:dpwpf="... namespace of dpwpf"

<Window.Resources>
    <DataTemplate DataType="{x:Type dpwpf:Contact}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding LastName}">
            <TextBlock Text=" ">
            <TextBlock Text="{Binding FirstName}">
        </StackPanel>
    </DataTemplate>
</Window.Resources>

这允许您定义在窗口中的任何地方如何显示Contact对象。如果您想将其限制为ComboBox,可以将DataTemplate添加到ComboBox资源中。


哇,我得让这个消化一下,你在一个ComboBoxItem内部使用了一个StackPanel。所以,上面发布的答案代码是有效的,但我没有看到我的ComboBox和DataTemplate之间的连接,我期望DataTemplate有一个名称,而ComboBox引用它。 - Edward Tanguay
组合框显示联系人对象。因此,WPF会在可视树中搜索显示联系人的DataTemplate,并使用该模板。如果没有模板,则默认使用ToString。除了通过联系人对象之外,没有直接连接。 - Cameron MacFarland
这就是WPF的美妙之处。你定义了一个显示数据对象的方式,然后无论该对象在哪里出现,都会使用模板来显示它。 - Cameron MacFarland
另外,StackPanel 只是为了实现“firstname” + “lastname”的效果而存在的。你也可以使用绑定转换器来实现相同的功能,但这种方式更简单。 - Cameron MacFarland
当像这样绕过问题时,自动完成功能将无法正常工作。请查看Rafa的答案。 - Alex Maker

7
只需在您的ComboBox标记中添加此内容(xaml代码)
TextSearch.TextPath ="Title"

ToString()修改会影响到你未来需要使用它的所有情况,我不建议你这样做。

看看这个例子:http://simplesample.site90.com/wpf_combobox.php


我知道它是像TextSearch.TextPath这样的属性,但在那些建议ToStringDisplayMemberPath的选项中找到正确答案真的很难...谢谢! - Gman

6
绑定机制的作用是对被绑定类型调用ToString()方法。因为您没有重写ToString(),所以它只会显示命名空间.类型,而不是有用的内容。
正如rebelious所说,您可以使用DisplayMember来告诉绑定使用该名称的属性作为显示值,或者您可以像下面一样重写ToString()来显示自定义属性。
public void Contact
{
 public string FirstName { get; set; }
 public override string ToString()
 {
   return FirstName; 
 }
}

1
这很不错,但我可能有其他控件需要以不同的方式进行覆盖,据我所知,我只能获得一个覆盖。 - Edward Tanguay

3

你需要使用DisplayMember="TheValue"。

你可以在XAML或CLR中添加此内容,还要注意在代码中绑定而不是通过XAML。我认为这与您以前的问题有关,其中实现了通过ObjectDataProvider进行绑定。使用该示例并在XAML中添加DisplayMemeber="memeber"。

希望对你有所帮助, Eric


是的,这样可以工作,但我想能够格式化文本而不是组合框项,例如lastname +“ ”+ firstname。 - Edward Tanguay
嗨,Edward,抱歉让你等这么久。 你有几种解决问题的方法。 1)添加一个FullName属性,它返回this.lastname +“,”+ this.firstname,并将其用作显示成员。HH, Eric - user61477
  1. 使用 IValueConverter 来转换显示的值,你可以将其作为 XAML 中的静态资源使用,并添加 Converter XML 属性。
- user61477

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