具有值和文本的ComboBoxItem

时间:2015-10-14 18:18:52

标签: c# .net xaml windows-store-apps win-universal-app

我的目标是拥有一个ComboBox,其中每个下拉项都有一个特定的文本和一个与之关联的特定项目,例如,如果有人点击“等等” - 所选项目将为3。

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

3 个答案:

答案 0 :(得分:2)

高度重新尝试使用XAML控件绑定,但是,您可以通过Items属性在XAML中定义ComboBox项:

  <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属性,因此可以使用tag属性来保存相应的值。设置SelectedValuePath属性告诉ComboBox将哪个属性用作值。

答案 1 :(得分:1)

虽然利用数据绑定是推荐的路线,但您必须了解您是否使用数据绑定引擎并未改变如何正确使用ComboBox控件。

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

在使用MVVM / DataBinding的典型场景中,您可以绑定ItemsSource以基于任何Items对象自动生成IEnumerable;大多数视图模型都有以下例子:

public class InventoryViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Car> Cars { get; private set; }
}

<ComboBox ItemsSource="{Binding Path=Cars, Mode=OneWay}" ... />

请注意,该集合包含一堆Car个对象(不是ComboBoxItem个)。现在,无论您是通过DataBinding还是直接填充ComboBox,它仍然会创建ItemCollection。那么,如果你放弃了DataBinding路由,你怎么能得到Car的集合?您可以直接在ComboBox.Items范围内创建每个元素,或者通过资源而不是类(静态或动态资源)使用DataBinding。如果你不做任何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而不是ComboBoxItem的类型。 SelectedValuePath也可以设置为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都会在一天结束时使用Content方法中的ToString()对象。如果您不想创建自己的对象,可以始终使用KeyValuePair<TKey, TValue>对象,因为它可以存储KeyValue(密钥将是基础值,而价值将是友好的文本)。当然,Mehrzad Chehraz使用Tag属性的answer同样有效,因为Tag旨在存储任意值。

答案 2 :(得分:0)

您可以使用此

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

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