SelectedIndexProperty binding for ListPicker

Topics: Bootstrappers & IoC, Conventions
Oct 23, 2013 at 1:15 PM
Hi all!

I need to implement a ListPicker in my Windows Phone app, so I downloaded the Windows Phone Toolkit from NuGet and inserted the code in my XAML like this:
<toolkit:ListPicker x:Name="Items" >
        <toolkit:ListPicker.ItemTemplate>
                  <DataTemplate>
                          <TextBlock Text="{Binding PriceValue}" />
                  </DataTemplate>
        </toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
As you can see, I'm trying to bind with the Caliburn's name convention to a collection named Items, so the selectedItem should be called SelectedItem.
private ObservableCollection<Price> _items;
        public ObservableCollection<Price> Items
        {
            get { return _items; }
            set
            {
                _items = value;
                NotifyOfPropertyChange(() => Items);
            }
        }

        private Price _selectedItem;
        public Price SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                    _selectedItem = value;
                    NotifyOfPropertyChange(() => SelectedItem);
            }
        }
Unfortunatly, binding for SelectedItem property is not working correctly. So I've implemented a custom convention in the Bootstrapper file like this:
ConventionManager.AddElementConvention<ListPicker>(ItemsControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged")
                .ApplyBinding = (viewModelType, path, property, element, convention) =>
                {
                    if (ConventionManager.GetElementConvention(typeof(ItemsControl))
                        .ApplyBinding(viewModelType, path, property, element, convention))
                    {
                        ConventionManager.ConfigureSelectedItem(element, ListPicker.SelectedItemProperty, viewModelType, path);

                        return true;
                    }

                    return false;
                };
This seems to work, but only seems. The problem I'm seeing is that when I select a new item, the SelectedItem property updates correctly, but the ListPicker show as selected item just the first item in Items (the collection).

Example:
Collection with this value: A, B, C, D.
Default selected item on page activating: A
Open ListPicker FullMode to change item to B
SelectedItem changes to B
ListPicker's FullMode closes and selected item changes to A.


Has anybody an idea on how to change this behavior?

Thanks in advance and sorry for my english! :)
-Matteo
Oct 23, 2013 at 1:33 PM
The reason the default convention does not work is caused by the fact that ListPicker does not inherit from Selector, so your custom convention is indeed required.
Now, I am not a WP developer, and my help can be limited, but I tried to have a look at the ListPicker source code, and noticed that it tries to keep sychronized both SelectedItem and SelectedIndex. The logic seems fine, but I guess it is better to check if the SelectedIndex property changes when needed.
Moreover, the ListPickerItem is quite different from a container used by selectors (tipically, such a container should provide a public two-way binadable IsSelected property, that is used both for displayind the selected state, or selecting an item, while the toolkit implementation simply uses the VisualStateManager).

I fear that you need to debug everyithing deeper, checking first if the internal state of the ListPicker (check for coherence between SelectedIndex and SelectedItem) and then the IsSelected internal property value in the ListPickerItem.
Oct 23, 2013 at 1:50 PM
Edited Oct 23, 2013 at 2:14 PM
Thanks for your answer!

What do you think about adding a new custom convention for the SelectedIndex property? It should work but I'm not sure because it's not a settable property...

Or should I just change the ListPicker with a custom control so I can solve this problem directly?


EDIT: SOLUTION FOUND!

I was doing an error! I wasn't considering that the OnActivate method is called each time the view needs to be loaded.
The method was previously used for initializing the Items collection and so each time the method was called (because the FullMode of the ListPicker closes) a new collection was instantiated replacing the SelectedIndex with the first item of the collection as default behavior. Replacing this with a sample control on the collection solved this problem.

Old:
protected override async void OnActivate()
{
         base.OnActivate();
         Items = new ObservableCollection<Price>();
}
New:
protected override async void OnActivate()
{
        base.OnActivate();
        
        if (Items == null)
               Items = new ObservableCollection<Price>();
}
-Matteo
Marked as answer by xTuMiOx on 10/23/2013 at 7:03 AM