The project was built using VS2012 and targeting .NET 4.
Table of Contents
Introduction
I've seen this question pop around, and wanted to have a 1 stop reference to solve the issue for people trying to figure it out.
They say a picture is worth a 1000 words, so here's a picture:
I say a demo is worth a 1000 pictures, so feel free to download the code and play with it yourself.
This is not a new topic, as you can easily see if you'll look here, here, here or on the official MSDN page here. (Do note that on the official MSDN (at the time of writing this), 0 out of 4 rated it helpful).
SelectedItem
: This will return the currently selected item in the list/combobox/container. This is an Object as you can see (since my list holds objects). If your List/Combobox/etc. contains a list of strings, it'll be a string. If it contains ints, it'll be an int.
SelectedValuePath
: Setting this will make the property SelectedValue
return the value of the property you have selected here. In our example, selecting "ShapeColor
" will make the SelectedValue
return only the color, and not the whole shape object.
Note: You set the property name as a string here. Look at the example in the demo code below for code.
SelectedValue
: If you want only a part of an object, set the above property, and you'll get the value of that property here. Note that if SelectedValuePath
is not used, this is the same as using SelectedItem
.
DisplayMemberPath
: Setting this to a property of an object, will cause the GUI to show that property when the class is selected instead of seeing the Class name or your Class ToString()
method (which should always be provided. Look at Item 5, Chapter 1 in this book's ToC or scroll down and read the whole thing :).
I wanted to keep this as simple and short as can be, while delivering enough punch to be interesting. I use a simple XAML file with some Code Behind, and it all clocks in at some 200 lines of code (including spaces and some comments).
MainWindow.xaml
Holds a DockPanel
with a footer at the bottom and a StackPanel
that will fill the window (last child by default does this).
Since I'm not using MVVM in this example, I'm binding things together by giving the Window a name, and then referring to this name in the Binding ElementName
. The path
will point to the matching Property on the Code Behind file.
Window x:Class="SelectedValue_and_SelectedItem.MainWindow"
... Name="SelectionFun" >
<ListBox Name="SourceListBox"
ItemsSource="{ Binding ElementName=SelectionFun, Path=ShapeCollection}" />
This covers the first part, creating and binding the objects to our list, so you can select a shape.
The second area holds a couple of ComboBox
es where you can choose the properties you'll want to bind/see, and some labels that will show you what is actually selected. I've also binded part of the grid to the shape's color to have some extra visual feedback.
The ComboBox
es look like this:
<ComboBox ...
ItemsSource="{ Binding ElementName=SelectionFun, Path=PropertiesList}"
SelectionChanged="DisplayMemberPathCmbx_SelectionChanged" />
The labels are straight forward, so let's move along.
MainWindow.xaml.cs - The Code Behind
The structure I'm using for my objects is a dummy MyShape
that looks like this:
public class MyShape
{
public string ShapeType { get; set; }
public string ShapeColor { get; set; }
public int ShapeSides { get; set; }
}
A method called GetShapesList()
will populate our list of shapes with objects like:
return new ObservableCollection<MyShape> {
new MyShape{ShapeType = "Circle", ShapeColor = "Blue", ShapeSides = 0 },
new MyShape{ShapeType = "Triangle", ShapeColor = "Yellow", ShapeSides = 3 }, ... }
(While the sides are the actual shape's sides, the colors are just random colors I've added.)
Things get interesting when we get to the PropertiesList
, which is populated like this:
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;
}
The PropertyObject
is a simple class to hold the Name
and the Type
of the property we're dealing with (both are string
s).
public class PropertyObject
{
public string PropertyName { get; set; }
public string PropertyType { get; set; }
}
First, we'll add an empty one, so when selected, it will "reset" the binding to the default.
We'll then use reflection to find all the properties on the MyShape
class so we can select them from the ComboBox
. Feel free to add more properties, or generalize this method to take a Class
as an argument, and then just pass your own custom Class
to see it in action.
The SelectionChanged
events simply set the ListBox
source properties according to what is selected (we called it SourceListBox
in the XAML) . For example:
private void DisplayMemberPathCmbx_SelectionChanged
(object sender, SelectionChangedEventArgs e) {
ComboBox cmbx = (ComboBox)sender;
PropertyObject prop_ob = ((PropertyObject)cmbx.SelectedItem);
string name = prop_ob.PropertyName;
SourceListBox.DisplayMemberPath = name;
}
That's it! Download the code and give it a spin to see it in action. :)
Points of Interest
I'm usually tending toward MVVM these days, but I wanted to keep the code brief, so I've opted for the code behind approach.
Note the use of reflection to dynamically get the properties and their type, and the way we bind the XAML to our properties with the use of names.
History
- 21st October, 2013: Initial release
Feel free to leave a comment, feedback and/or ask any question.