具有值和文本的组合框项

本文关键字:组合 文本 | 更新日期: 2023-09-27 18:17:39

我的目标是有一个ComboBox,其中每个下拉项都有一个特定的文本和一个与之关联的特定项,例如,如果某些人单击"blah" - 所选项将为 3。

据我所知 - 只有一个"内容"同时代表文本和值。那么我如何分别获得两者呢?(在 XAML 或代码中,但没有绑定

具有值和文本的组合框项

XAML 控件使用绑定是高度重新开始的,但是,可以通过 Items 属性在 XAML 中定义组合框项:

  <ComboBox x:Name="comboBox1"
            SelectionChanged="ComboBox_SelectionChanged"
            SelectedValuePath="Tag">
     <ComboBox.Items>
        <ComboBoxItem Tag="1">Item 1</ComboBoxItem>
        <ComboBoxItem Tag="2">Item 2</ComboBoxItem>
        <ComboBoxItem Tag="3">Item 3</ComboBoxItem>
     </ComboBox.Items>
  </ComboBox>

并在代码中获取选定的项目:

 private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
     Debug.WriteLine(comboBox1.SelectedValue);
  }

由于 ComboBox 项类没有 Value 属性,因此可以使用标记属性来保存相应的值。属性的设置告诉组合框将哪个属性用作值。

虽然建议使用数据绑定,但您必须了解,无论是否使用数据绑定引擎都不会更改正确使用 ComboBox 控件的方式。


ComboBox有一个Items性质,它只是一个ItemCollection,而又是object s的专门枚举。因此,了解这一点后,您可以将任何object添加到项目集合中,无论类型如何。

在使用 MVVM/DataBinding 的典型方案中,您将绑定ItemsSource以基于任何IEnumerable对象自动生成Items;大多数视图模型都会有以下内容作为示例:

public class InventoryViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Car> Cars { get; private set; }
}
<ComboBox ItemsSource="{Binding Path=Cars, Mode=OneWay}" ... />

请注意,集合有一堆Car对象(不是 ComboBoxItem 个(。现在,无论您是通过数据绑定填充ComboBox还是直接填充,它仍将创建一个ItemCollection。那么,如果您放弃数据绑定路由,如何获得Car的集合?可以直接在ComboBox.Items范围内创建每个元素,也可以通过资源而不是类(静态或动态资源(使用 DataBinding。如果不执行任何数据绑定(甚至对资源(,则代码将如下所示:

<ComboBox ... >
  <ComoBox.Items>
     <local:Car Brand="Ford" Model="Mustang" Id="1" />
     <local:Car Brand="Ford" Model="Fusion"  Id="2" />
     <local:Car Brand="Cadillac" Model="CTS" Id="3" />
  </ComboBox.Items>
</ComboBox>

有了这个,您可能需要为ComboBox设置的唯一其他属性DisplayMemberPath属性。我说可能是因为如果不设置此值,ComboBox将在对象上调用ToString()以获取对象的字符串版本,因此这取决于Car类是否具有自定义ToString()。现在,当您听SelectionChangedEvent时,SelectedItem将是一种Car而不是ComboBoxItemSelectedValuePath也可以设置为 Car 的属性,您也可以获取SelectedValue而不是整个SelectedItem,但就像以前一样,实际的基础类型将是特定类型而不是ComboBoxItem


附加信息:

ComboBoxItem不需要设置DisplayMemberPath的原因是ToString()成员返回 Content 属性的格式化版本:

public partial class FrameworkElement
{
    internal virtual string GetPlainText()
    {
        return null;
    }
}
public class Control : FrameworkElement
{
    public override string ToString()
    {
        string plainText = null;
        if (CheckAccess())
        {
            plainText = GetPlainText();
        }
        else
        {
            plainText = (string)Dispatcher.Invoke(DispatcherPriority.Send, new TimeSpan(0, 0, 0, 0, 20), new DispatcherOperationCallback(delegate(object o) {
                    return GetPlainText();
                }), null);
        }
        if (!String.IsNullOrEmpty(plainText))
        {
            return SR.Get(SRID.ToStringFormatString_Control, base.ToString(), plainText);
        }
        return base.ToString();
    }
}
public class ContentControl : Control
{
    internal override string GetPlainText()
    {
        return ContentObjectToString(Content);
    }
    internal static string ContentObjectToString(object content)
    {
        if (content != null)
        {
            FrameworkElement feContent = content as FrameworkElement;
            if (feContent != null)
            {
                return feContent.GetPlainText();
            }
            return content.ToString();
        }
        return String.Empty;
    }
}
public class ListBoxItem : ContentControl { }
public class ComboBoxItem : ListBoxItem { }

基本上,任何ContentControl都将在一天结束时在 ToString() 方法中使用 Content 对象。如果您不想创建自己的对象,则始终可以使用KeyValuePair<TKey, TValue>对象,因为它可以存储KeyValue(键是基础值,而值将是友好文本(。当然,Mehrzad Chehraz 使用 Tag 属性的答案同样有效,因为Tag用于存储任意值。

你可以使用这个

<ComboBox Height="154" HorizontalAlignment="Left" 
         ItemsSource="{Binding Path=Books}"
         DisplayMemberPath="Title">
</ComboBox>

其中 Title 是类Book的成员 Books - Book 对象的集合