15
Vote

ListPicker - SelectedItem must always be set to a valid value

description

Steps to reproduce...

Add ListPicker to page
Bind ListPicker SelectedItem to property on DataContext
Set DataContext to null or simply try to clear the binding and boom...

at Microsoft.Phone.Controls.ListPicker.OnSelectedItemChanged(Object oldValue, Object newValue)
at Microsoft.Phone.Controls.ListPicker.OnSelectedItemChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.RaisePropertyChangeNotifications(DependencyProperty dp, Object oldValue, Object newValue)
at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.ClearValueInternal(DependencyProperty dp)
at System.Windows.DependencyObject.ClearValue(DependencyProperty dp)
at NotImportant_Unloaded_1(Object sender, RoutedEventArgs e)
at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

comments

Will_o_Wisp wrote Jan 13, 2013 at 4:21 PM

Same thing happens if the SelectedItem is set before ItemsSource, which happens for me when bindings are defined in XAML file. Now I have to move the SelectedItem binding the the code behind, manually adding it in the Loaded event for the page, in order to make sure it is not set before the ItemsSource is set.

max2 wrote Jan 20, 2013 at 3:20 AM

Moving ItemsSource attribute in front of SelectedItem attribute with binding in XAML solved my problem here.

yudayyy wrote Mar 7, 2013 at 3:21 AM

Same things happens to me, moving the SelectedItem after the ItemsSource didnt solve my problem, I'm using MVVM, so the binding is in my viewmodel.

How do I get this thing work?

T_Ball wrote Mar 9, 2013 at 5:18 PM

Same thing happens when you bind both ItemsSource and SelectedIndex to your Viewmodel.
Sometimes it helps to move ItemsSource before SelectedIndex, but then if ItemsSource is bound to another ViewModel, that loads a bit slower, you get the same error.
I could not find a good workaround fro this issue. Also the designer crashes all the time with this exception.
For me it makes the control hardly unusable. It would be great if someone could have a look at it.

jbond wrote May 16, 2013 at 9:37 PM

So Microsoft has a bug in their toolkit which makes using one of the most popular controls IMPOSSIBLE, and it remains unfixed for months without so much as a single comment?

Whoever is responsible for the toolkit ought to be fired and replaced by someone who actually gives a shit.

Oliver_Braun wrote Jun 5, 2013 at 10:03 AM

I experienced this issue too. Setting the value code-behind worked, although it isn't the most beautiful solution. A fix would be very much appreciated.

jagui wrote Sep 30, 2013 at 3:53 PM

had to resort to code behind, not good....

MaxMeng wrote Dec 5, 2013 at 6:19 AM

Oh dear MS, why you make a user control so hard to use, I have been struggling with this for weeks, and it just doesn't wokr, I only wish I have spent these time developing my apps.

SolalPirelli wrote Dec 15, 2013 at 6:14 PM

This isn't low priority, it should be a blocker for whatever the next release is.

marcelodeaguiar wrote Sep 11 at 7:53 PM

My take on this was to create a Behavior to delay the binding until the ListPicker is completle loaded and just then the bind to the real SelectedItem.
namespace Fluig.WP8.UI.Interactivity {

    using Microsoft.Phone.Controls;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Interactivity;

    /// <summary>
    /// This class is a hack for a know bug in ListPicker where the binding in SelectedItem and SelectedIndex fire
    /// before the ItemsSource is ready. More details here: http://phone.codeplex.com/workitem/10665
    /// 
    /// The trick is to delay the bind until the control is loaded.
    /// </summary>
    public class DelayedListPickerBinderBehavior : Behavior<ListPicker> {

        public static object GetSelectedItem( DependencyObject obj ) {
            return (object)obj.GetValue( SelectedItemProperty );
        }

        public static void SetSelectedItem( DependencyObject obj, object value ) {
            obj.SetValue( SelectedItemProperty, value );
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.RegisterAttached( "SelectedItem", typeof( object ), typeof( ListPicker ), new PropertyMetadata( null ) );

        protected override void OnAttached() {
            base.OnAttached();
            this.AssociatedObject.Loaded += AssociatedObject_Loaded;
        }


        protected override void OnDetaching() {
            base.OnDetaching();
            this.AssociatedObject.Loaded -= AssociatedObject_Loaded;

        }

        void AssociatedObject_Loaded( object sender, RoutedEventArgs e ) {
            // Get the bind expression from the attached property and if it is a binding then 
            // bind to the real SelectedItem.
            var expression = this.AssociatedObject.GetBindingExpression( DelayedListPickerBinderBehavior.SelectedItemProperty );
            if (null != expression) {
                BindingOperations.SetBinding( this.AssociatedObject, ListPicker.SelectedItemProperty, expression.ParentBinding );

            }
        }
    }
Then in Xaml
                <toolkit:ListPicker Header="Cache"
                                    uii:DelayedListPickerBinderBehavior.SelectedItem="{Binding Path=Tenant.CacheTimeout, Converter={StaticResource IntervalLiterals}, Mode=TwoWay}"
                                    ItemsSource="{Binding Source={StaticResource IntervalLiterals}, Path=Intervals}">
                    <i:Interaction.Behaviors>
                        <uii:DelayedListPickerBinderBehavior />
                    </i:Interaction.Behaviors>
                </toolkit:ListPicker>
.