2015-10-14 2 views
2

Моя цель состоит в том, чтобы иметь ComboBox, где каждый выпадающий элемент имеет определенный текст и определенный элемент, связанный с ним, так что, например, если некоторые клики «бла» - выбранный элемент будет 3.ComboBoxItem с значениями и текстом

Насколько я вижу - есть только одно «Содержание», которое представляет собой текст и значение. Итак, как мне получить оба отдельно? (. В любом XAML или код, но без привязки)

ответ

2

It настоятельно рекомендуется использовать привязку с элементами управления XAML, однако вы можете определить элементы ComboBox в XAML по свойству Items:

<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, вы можете использовать свойство тег для хранения соответствующего значения. Настройки Свойство SelectedValuePath сообщает ComboBox, какое свойство использовать в качестве значения.

0

Вы можете использовать этот

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

где Название является членом Book класса Books - коллекция Book объектов

+0

Спасибо. Но есть ли способ сделать это без привязки. Просто что-то вроде ' ispiro

+0

Я отредактировал вопрос. – ispiro

0

Использование преимуществ привязки данных является рекомендуемым маршрутом, вы должны понимать, что независимо от того, используете ли вы механизм привязки данных, не следует изменять, как правильно использовать элемент управления ComboBox.


ComboBox имеет Items свойство, которое просто просто ItemCollection, в свою очередь, является специализированным перечисление object с. Итак, зная это, вы можете добавить любые 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 с). Теперь, заполнив ли вы ComboBox через DataBinding или напрямую, он все равно будет создавать 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>, так как он может хранить Key и Value (ключ будет базовым значением, тогда как значение будет дружественным текстом). Конечно, Mehrzad Chehraz's answer с использованием свойства Tag так же важен, поскольку Tag предназначен для хранения любых произвольных значений.

Смежные вопросы