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 useSelectedIndex
.If
SelectedObject
may not be considered.Equals()
to any item in yourItems
list, useSelectedIndex
. This is becauseSelectedItem
compares objects with theItems
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 aSelectedObject
property.If you need to reference only one of
SelectedObject
orSelectedIndex
in other parts of your code, use that one.If your data models already have a
SelectedIndex
orSelectedObject
property, then use that.If all other things are equal, I use a
SelectedObject
property to bind theSelectedItem
property.This is because to me it makes more sense to refer to something like
SelectedUser
instead ofSelectedUserIndex
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.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.
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.
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.