如何基于数据绑定在WPF ComboBox中选择一个项目?

6

我已将我的DataContext设置为Book对象。Book有Title和Category两个属性。

我有一个CollectionViewSource“categoryList”,它保存了一个类别列表。

问题: 我该如何在这个组合框中选择书的类别?

<TextBox Text="{Binding Path=Title}"/>

<ComboBox SelectedValuePath="Id" 
          SelectedValue="{Binding Path=Category.Id}" 
          SelectedItem="{Binding Path=Category}"
          ItemsSource="{Binding Source = {StaticResource categoryList}}" 
          DisplayMemberPath="Name" />

上面的代码正确显示了书的标题,然后在组合框中显示类别名称列表。但它没有选择书的类别。相反,它只选择列表中的第一项。

2个回答

6
您绑定了太多内容;您只需要设置SelectedValueSelectedValuePathSelectedItem。在这种情况下,看起来您实际上是要绑定到特定对象。如果您想让ComboBox设置您的Book上的Category属性,并且当前的Book对象实际上引用了categoryList中的一个Category实例,则应使用SelectedItem绑定并删除SelectedValueSelectedValuePath的绑定。

编辑

稍微解释一下如何完成此操作,SelectedValue旨在在您的绑定项与列表源上的属性之间存在公共信息时使用。例如,假设我有一个带有CategoryID属性的Book类。

public class Book
{
    public string CategoryID { get; set; }
    public string Title { get; set; }
}

public class CategoryID
{
    public string ID { get; set; }
    public string Name { get; set; }
}

在这种情况下,您需要执行以下操作:
<ComboBox SelectedValue = "{Binding CategoryID}"
          SelectedValuePath = "ID"
          DisplayMemberPath = "Name" />

SelectedItem是用于绑定实例与绑定列表中实际引用(或更精确地说,等同于)项目的情况。因此,假设Book类实际上看起来像这样:

public class Book
{
    public Category Category { get; set; }
    public string Title { get; set; }
}

在这种情况下,你需要执行以下操作:
<ComboBox SelectedItem = "{Binding Category}"
          DisplayMemberPath = "Name" />

但是需要注意的是,只有当Book类引用与列表中的Category实例相同时,这才能起作用。如果引用不同(即使类上的值相等),则无法工作,因为ComboBox将无法在列表中找到Book中引用的Category。
你在上面绑定的真正问题(通过绑定到Category.ID)是你混合了方案。你有一个引用,但你试图绑定键。所有这些做的只是尝试在引用上设置值,而不会尝试更改类上的引用

抱歉,是的,我只是把所有东西都扔出来了。 :) SelectedValue + SelectedValuePath不起作用。SelectedItem本身也不起作用。甚至像Doug下面展示的SelectedItem + SelectedValuePath也不行。唉。我认为categoryList的类别在某种程度上干扰了我获取书籍类别的能力(如果我直接绑定到下面的文本字段中的Category.Name,我会得到错误的值。但是如果我注释掉对categoryList的绑定,那么值就是正确的)。我将尝试他的调试建议。谢谢。 - Abby Fichtner
这真的很有帮助,谢谢。尽管我不理解为什么还要加上isSynchronizedWithCurrentItem=True才能让它工作(我正在使用你上面展示的SelectedItem)。 - Abby Fichtner
@Abby:你是否将这个 Category 对象列表绑定到其他数据源?如果是的话,那就有意义了。 - Adam Robinson

1

用代码来描述Adam所谈论的内容:

<ComboBox 
     SelectedValuePath="Id"
     SelectedItem="{Binding Path=Category}"
     ItemsSource="{Binding Source={StaticResource categoryList}}"
     DisplayMemberPath="Name" />

可能更合适。通常最好将SelectedValue视为只读,并使用SelectedItem来选择要选中的项目。当将SelectedItem绑定到书籍的Category时,它会自动为您设置SelectedValue属性。

如果仍然不起作用,您可能需要检查对Category的绑定是否正常工作。特别是,添加一个DebugConverter可以很好地确保您期望的值被正确绑定。您可以看到使用DebugConverter是解决此问题的答案。

-Doug


这是正确的(尽管在这种情况下SelectedValuePath不是必需的),只有当绑定对象与列表中的元素共享相同的引用时才成立。如果它们是不同的引用但共享一个公共键,则这是不正确的。 - Adam Robinson
哇,谢谢你提供的调试思路 - 真是太棒了。我使用它并发现它在某种程度上将我的类别值(在ConvertBack中)设置为ComboBox列表中的第一个项目。现在我真的很困惑。但至少有了更好的工具,感谢你。 - Abby Fichtner
而且这个问题(只是为了跟进)通过添加IsSynchronizedWithCurrentItem=True来解决,尽管我不清楚为什么。 - Abby Fichtner
没问题,Abby - DebugConverter 在不止一次的场合下拯救了我的生命。 :) - Doug

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