具有值和文本的 ComboBoxItem
ComboBoxItem with both Value and Text
我的目标是 ComboBox
每个下拉项目都有一个特定的文本和一个与之关联的特定项目,例如,如果点击 "blah" - 所选项目将是 3.
据我所知 - 只有一个 "Content" 同时代表文本和值。那么我如何分别获得两者呢? (在 XAML 或代码中,但 没有绑定 。)
你可以用这个
<ComboBox Height="154" HorizontalAlignment="Left"
ItemsSource="{Binding Path=Books}"
DisplayMemberPath="Title">
</ComboBox>
其中标题是 Book
class Books
- collection 的 Book
objects
的成员
强烈建议使用绑定 XAML 控件,但是,您可以在 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);
}
由于组合框项目class没有值属性,您可以使用标签属性来保存相应的值。设置 SelectedValuePath 属性 告诉 ComboBox 哪个 属性 用作值。
虽然利用数据绑定是推荐的途径,但您必须明白,无论您是否利用数据绑定引擎都不会改变 ComboBox
控件的正确使用方式。
ComboBox
has an Items
property, which is simply just an ItemCollection
又是 object
的专门枚举。因此,了解这一点后,您可以将任何 object
添加到项目集合中,而不考虑类型。
在使用 MVVM/DataBinding 的典型场景中,您将根据任何 IEnumerable
对象将 ItemsSource
绑定到 auto-generate 和 Items
;大多数 view-models 会以下面的例子为例:
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
范围内创建每个元素,或者通过资源而不是 class(静态或动态资源)使用 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
class 是否有自定义 ToString()
。现在,当您收听 SelectionChangedEvent
时,SelectedItem
将是 Car
的一种类型,而不是 ComboBoxItem
。 SelectedValuePath
也可以设置为 Car
的 属性 并且您还可以得到 SelectedValue
而不是整个 SelectedItem
,但与实际之前一样基础类型将是特定类型而不是 ComboBoxItem
.
附加信息:
ComboBoxItem
不需要设置 DisplayMemberPath
的原因是 ToString()
成员 returns 是 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>
对象,因为它可以存储 Key
和 Value
(键是基础值,而值将是友好的文本)。当然,Mehrzad Chehraz 的 使用 Tag
属性 同样有效,因为 Tag
是用来存储任意值的。
我的目标是 ComboBox
每个下拉项目都有一个特定的文本和一个与之关联的特定项目,例如,如果点击 "blah" - 所选项目将是 3.
据我所知 - 只有一个 "Content" 同时代表文本和值。那么我如何分别获得两者呢? (在 XAML 或代码中,但 没有绑定 。)
你可以用这个
<ComboBox Height="154" HorizontalAlignment="Left"
ItemsSource="{Binding Path=Books}"
DisplayMemberPath="Title">
</ComboBox>
其中标题是 Book
class Books
- collection 的 Book
objects
强烈建议使用绑定 XAML 控件,但是,您可以在 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);
}
由于组合框项目class没有值属性,您可以使用标签属性来保存相应的值。设置 SelectedValuePath 属性 告诉 ComboBox 哪个 属性 用作值。
虽然利用数据绑定是推荐的途径,但您必须明白,无论您是否利用数据绑定引擎都不会改变 ComboBox
控件的正确使用方式。
ComboBox
has an Items
property, which is simply just an ItemCollection
又是 object
的专门枚举。因此,了解这一点后,您可以将任何 object
添加到项目集合中,而不考虑类型。
在使用 MVVM/DataBinding 的典型场景中,您将根据任何 IEnumerable
对象将 ItemsSource
绑定到 auto-generate 和 Items
;大多数 view-models 会以下面的例子为例:
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
范围内创建每个元素,或者通过资源而不是 class(静态或动态资源)使用 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
class 是否有自定义 ToString()
。现在,当您收听 SelectionChangedEvent
时,SelectedItem
将是 Car
的一种类型,而不是 ComboBoxItem
。 SelectedValuePath
也可以设置为 Car
的 属性 并且您还可以得到 SelectedValue
而不是整个 SelectedItem
,但与实际之前一样基础类型将是特定类型而不是 ComboBoxItem
.
附加信息:
ComboBoxItem
不需要设置 DisplayMemberPath
的原因是 ToString()
成员 returns 是 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>
对象,因为它可以存储 Key
和 Value
(键是基础值,而值将是友好的文本)。当然,Mehrzad Chehraz 的 Tag
属性 同样有效,因为 Tag
是用来存储任意值的。