I'm trying to do a two way binding of the SelectedIndex attribute of a ListPicker in a Windows Phone 7 UserControl.
It raises the following exception when I set the DataContext:
SelectedIndex must always be set to a valid value.
This is the XAML code
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<toolkit:ListPicker
Grid.Row="0"
x:Name="List1"
SelectionChanged="Picker_SelectionChanged"
SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}"
ItemTemplate="{StaticResource PickerTemplate}"
ItemsSource="{Binding MyList}"/>
</Grid>
And the code behind in DataContext
private ObservableCollection<MyClass> myList = null;
public ObservableCollection<MyClass> MyList
{
get { return this.myList; }
set
{
if (value != this.myList)
{
this.myList= value;
NotifyPropertyChanged("MyList");
this.PickerSelectedIndex = 0;
}
}
}
private int pickerSelectedIndex = 0;
public int PickerSelectedIndex
{
get
{
return this.pickerSelectedIndex;
}
set
{
this.pickerSelectedIndex= value;
}
}
Putting a breakpoint in PickerSelectedIndex.get
I can see that it is returned correctly (0
).
I am sure that the problem is SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}"
because deleting this line solves the problem, and I can see the ListPicker correctly loaded with the data from MyList.
I can't see where is the problem...
I've found the same problem with my app. But I noticed that it happens when I delete all the elements of the list bounded to the ListPicker in the ViewModel. So it isn't necessary to Bind SelectedIndex with another property since the problem depends only on the list bounded. Here is my code which work fine for me:
The list in view model:
The handler for SelectionChanged:
Where Corsi is the class type of the list.
Here ListPicker template:
And, in the end, the method delete that checks if the list returned by IsolatedStorage is empty, if so, I put a fake empty element in the list bounded to the ListPicker, in order to not receive the error mentioned in this post.
The strange thing was that, if the list was empty when the page has been loaded, nothing happens, instead, when I removed the last element from the list, the application raised the exception "SelectedItem must always be set to a valid value". Now the problem is solved.
My guess would be that the binding is being applied with a default value of zero when created and before the items exist. It's therefore trying to select the first item (with a zero index) before that item is created.
Try making sure that the ViewModel property of
PickerSelectedIndex
defaults to -1.You may also want to delay setting the binding until the items are created.
I had the same issue and the ordering of the properties in XAML didn't help. In my case, I was binding ItemsSource to a property on a StaticResource, but I was binding SelectedIndex with a property of my page's ViewModel. The moment I changed the binding of ItemsSource to bind to a property on the ViewModel itself (i.e. duplicated a property of the StaticResource), my issue went away and I was able to perform 2-way binding on SelectedIndex as well.
Moving
SelectedIndex
afterItemsSource
solved the problem.This is the working snippet
Anyone have an explanation for this?
Matt Lacey is right; binding happens before the data items get populated & hence the error. If you have an event handler for SelectionChanged, you will notice that a breakpoint in it will be hit as the page/listpicker loads. Here is one way to get around this initialization issue: