65.9K
CodeProject 正在变化。 阅读更多。
Home

理解 SelectedValue、SelectedValuePath、SelectedItem 和 DisplayMemberPath + 演示

starIconstarIconstarIconstarIconstarIcon

5.00/5 (20投票s)

2013年10月21日

CPOL

4分钟阅读

viewsIcon

112638

downloadIcon

2816

梳理这些属性的混淆之处,并提供一个演示应用程序

项目使用 VS2012 构建,目标为 .NET 4。

目录

引言

我看到这个问题经常出现,所以想提供一个一站式参考,帮助那些想弄明白的人解决这个问题。

快速概览 -> 截图

他们说一图胜千言,所以这里有一张图

我认为一个演示胜过千张图片,所以请随意下载代码并亲自尝试一下。

额外阅读 -> 文字解释

这不是一个新话题,如果你看看 这里这里这里 或官方 MSDN 页面 这里,就能很容易地看到。(请注意,在撰写本文时,官方 MSDN 上的评分是 4 条评论中有 0 条认为有帮助)。

SelectedItem:此属性将返回列表/组合框/容器中当前选定的项。如你所见,这是一个 Object (因为我的列表包含对象)。如果你的 List/Combobox/etc. 包含字符串列表,它将是字符串。如果包含 int,它将是 int。

SelectedValuePath:设置此属性将使 SelectedValue 属性返回此处选择的属性的值。在我们的示例中,选择 "ShapeColor" 将使 SelectedValue 只返回颜色,而不是整个形状对象。

注意:您在此处将属性名设置为字符串。请查看下方演示代码中的示例以获取代码。

SelectedValue:如果你只需要对象的一部分,请设置上面的属性,你将在此处获得该属性的值。请注意,如果未使用 SelectedValuePath,则此属性等同于使用 SelectedItem

DisplayMemberPath:将其设置为对象的某个属性,当选中该类时,GUI 将显示该属性,而不是显示类名或你的类 ToString() 方法 (你应该始终提供该方法。查看此 书籍的目录 的第 5 项,第 1 章,或向下滚动阅读全文 : )。

Using the Code

我希望保持内容尽可能简单和简短,同时又能提供足够的信息来引起兴趣。我使用了一个简单的 XAML 文件和一些代码隐藏,总共大约有 200 行代码 (包括空格和一些注释)。

MainWindow.xaml

包含一个 DockPanel,底部有一个页脚,以及一个 StackPanel,它将填满窗口 (默认情况下,最后一个子元素会这样做)。

由于在此示例中我没有使用 MVVM,所以我通过给 Window 命名来将事物绑定在一起,然后在 Binding ElementName 中引用该名称。path 将指向代码隐藏文件中的匹配属性。

Window x:Class="SelectedValue_and_SelectedItem.MainWindow"
	... Name="SelectionFun" >
 <ListBox Name="SourceListBox"  
	ItemsSource="{ Binding ElementName=SelectionFun, Path=ShapeCollection}" /> 

这涵盖了第一部分,创建对象并将其绑定到我们的列表,以便您可以选择一个形状。

第二部分包含几个 ComboBox,您可以在其中选择要绑定/查看的属性,以及一些标签,它们将显示实际选择的内容。我还将网格的一部分绑定到形状的颜色,以提供一些额外的视觉反馈。

ComboBoxes 的外观如下

<ComboBox	...
	ItemsSource="{ Binding  ElementName=SelectionFun, Path=PropertiesList}" 
	SelectionChanged="DisplayMemberPathCmbx_SelectionChanged" 	/> 

标签很简单,所以我们继续。

MainWindow.xaml.cs - 代码隐藏

我使用的对象结构是一个简单的 MyShape,如下所示

public class MyShape
{
    public string ShapeType  { get; set; }
    public string ShapeColor { get; set; }
    public int    ShapeSides { get; set; }
}  

一个名为 GetShapesList() 的方法将使用类似以下的结构填充我们的形状列表

return new ObservableCollection<MyShape> {	
    new MyShape{ShapeType = "Circle",    ShapeColor = "Blue",	ShapeSides = 0 },
    new MyShape{ShapeType = "Triangle",  ShapeColor = "Yellow",	ShapeSides = 3 },  ... } 

(虽然边是形状的实际边,但颜色只是我添加的随机颜色。)

当涉及到 PropertiesList 时,事情变得有趣起来,它填充如下

private static ObservableCollection<PropertyObject> GetPropertiesList()
{
  ObservableCollection<PropertyObject> return_collection = 
                               new ObservableCollection<PropertyObject> 
	{ new PropertyObject {PropertyName = "", PropertyType = "Reset to default"} };
 
  var propertiesInfos = typeof(MyShape).GetProperties();
  
  foreach (var propertyInfo in propertiesInfos)
  {
	return_collection.Add(new PropertyObject 
	{ PropertyName = propertyInfo.Name, 
	  PropertyType = propertyInfo.PropertyType.Name 
	});
  }
 
  return return_collection;
} 

PropertyObject 是一个简单的类,用于保存我们正在处理的属性的 NameType (两者都是 string)。

public class PropertyObject
{
  public string PropertyName { get; set; }
  public string PropertyType { get; set; }
} 

首先,我们会添加一个空的,所以当它被选中时,它将把绑定“重置”为默认值。

然后,我们将使用反射来查找 MyShape 类中的所有属性,以便我们可以从 ComboBox 中选择它们。随意添加更多属性,或将此方法通用化,使其接受一个 Class 作为参数,然后传递你自己的自定义 Class 来查看它的运行效果。

SelectionChanged 事件简单地根据所选内容设置 ListBox 源属性 (我们在 XAML 中称之为 SourceListBox)。例如

private void DisplayMemberPathCmbx_SelectionChanged
(object sender, SelectionChangedEventArgs e) {
  // Get the value
  ComboBox cmbx = (ComboBox)sender;
  PropertyObject prop_ob = ((PropertyObject)cmbx.SelectedItem);
  string name = prop_ob.PropertyName;

  // Actual setting happens here
  SourceListBox.DisplayMemberPath = name;
} 

就这样!下载代码并尝试一下,看看它的效果。 :)

关注点

我通常更倾向于 MVVM,但我想让代码简短,所以我选择了代码隐藏的方法。

请注意使用反射动态获取属性及其类型,以及我们如何通过使用名称将 XAML 绑定到我们的属性。

历史

  • 2013 年 10 月 21 日:初始发布

欢迎留下评论、反馈和/或提问。

© . All rights reserved.