Let's say that you have an observable collection of object type Foo, and you have a custom ListView that the user will select from.
Your bound data object:
// property with getter / setter / INotifyPropertyChanged
ObservableCollection<Foo> MyCollection;
In XAML:
<ListView ItemsSource={Binding MyCollection} />
Is it more appropriate to bind to the SelectedIndex in XAML and create the following in your data object:
int SelectedIndex { get; set; } // also raising property changed notifications
Foo SelectedObject
{
get { return MyCollection[SelectedIndex]; }
}
Or to create this and bind to the SelectedItem in XAML:
Foo SelectedObject { get; set; } // also raising property changed notifications
And why?
Both cases are acceptable, however which you choose usually depends on the design of your data models, and which method would require the least amount of code to get working.
A few rules I use to determine which one to select
If SelectedObject
cannot be null (such as an enum), and you need to default to be no item selected, then use SelectedIndex
.
If SelectedObject
may not be considered .Equals()
to any item in your Items
list, use SelectedIndex
. This is because SelectedItem
compares objects with the Items
collection using .Equals()
, so a reference comparism will return false which will result in your object not becomming selected.
This usually happens when your selected item comes from a different location than where your list of items is. For example, one database calls to load the Items
for the list, and a separate database call obtaining an object that includes a SelectedObject
property.
If you need to reference only one of SelectedObject
or SelectedIndex
in other parts of your code, use that one.
If your data models already have a SelectedIndex
or SelectedObject
property, then use that.
If all other things are equal, I use a SelectedObject
property to bind the SelectedItem
property.
This is because to me it makes more sense to refer to something like SelectedUser
instead of SelectedUserIndex
in the code behind, and I prefer to avoid looking up the item in the collection anytime I want to do something with the selected item.
Depends on your needs. If you need to set the selected item, you need the second version. If you need the selected item's index, you need the first version. If you need neither, it's up to your personal preference.
Both approaches are fine. Use the one you find easier to use. I don't find myself relying on indices often, but your cases may be different.
If you look at MVVM libraries, Caliburn.Micro, for example, expects you to use SelectedObject
approach. It explicitly supports this convention.
And note on collection properties. In general, it's better idea to have read-only auto-properties and set them in constructor (property change notification won't be necessary). It is not advised to change instances of collections. While WPF supports it, it's much easier to subsribe to collection events in your own code if the instance doesn't change.
I personal think bind to the SelectedObject is much cleaner unless you need access to the SelectedIndex
The only time I use SelectedIndex is when I want to set a default value of 0 to select the first item.