添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
仗义的冲锋衣  ·  SQLite Join | 菜鸟教程·  1 年前    · 
坐怀不乱的生菜  ·  Go Elasticsearch ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

My goal is to have a ComboBox where every drop down item has a specific text and a specific item associated with it so that, for example, if some clicks "blah" - the selected item will be 3.

As far as I can see - there's only one "Content" which represents both the Text and the Value. So how do I get both separately? (In either XAML or code, but without Binding .)

It is highly recommenced to use binding with XAML controls, however, you can define ComboBox items in XAML by the Items property:

  <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>

and get selected items in code:

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

Since the ComboBox item class has not a Value property, you can use the tag property to hold the corresponding value. Settings the SelectedValuePath property tells the ComboBox which property to use as Value.

The ComboBox has an Items property, which is simply just an ItemCollection, which in turn is a specialized enumeration of objects. So, in knowing this you can add any object regardless of type to the collection of items.

In a typical scenario utilizing MVVM/DataBinding you would bind the ItemsSource to auto-generate the Items based upon any IEnumerable object; most view-models would have the following as an example:

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

Notice that the collection has a bunch of Car objects (not ComboBoxItems). Now, whether or not you populate a ComboBox through DataBinding or directly, it will still create an ItemCollection. So, if you forego the DataBinding route, how can you get a collection of Cars? You could create each element directly within the ComboBox.Items scope, or use DataBinding through a resource instead of a class (static or dynamic resource). If you don't do any DataBinding (even to a resource), you're code would look like this:

<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>

With this in hand, the only other property you might need to set for the ComboBox is the DisplayMemberPath property. I say might because if you do not set this value, the ComboBox will call ToString() on the object to get the string version of the object, so it depends on whether or not the Car class has a customized ToString(). Now, when you listen to the SelectionChangedEvent, the SelectedItem will be a type of Car instead of ComboBoxItem. The SelectedValuePath can also be set to a property of Car and you can also get the SelectedValue instead of the entire SelectedItem, but just as before the actual underlying type would be a specific type instead of a ComboBoxItem.

Additional Information:

The reason why ComboBoxItem doesn't need a DisplayMemberPath to be set is because the ToString() member returns a formatted version of the Content property:

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();
            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 { }

Basically, any ContentControl will use the Content object in the ToString() method at the end of the day. If you didn't want to create your own object, you can always use the KeyValuePair<TKey, TValue> object as it can store a Key and a Value (the key would be the underlying value whereas the value would be the friendly text). Of course, Mehrzad Chehraz's answer of using the Tag property is just as valid, since Tag is meant to store any arbitrary value.

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

where Title is the member of Book class Books - collection of Book objects

Thanks. But is there any way to do that without binding. Just something like <ComboBoxItem Value = "3" Text = "blah" ... ? – ispiro Oct 14, 2015 at 18:59

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.