longlistselector with bindable selecteditem
In Windows Phone 8 Microsoft wants us to use the LongListSelector instead of the ListBox. But it seems they forgot about something, the SelectedItem property of the LongListSelector isn’t bindable. There are multiple work-arounds for this like event to command in XAML or setting the viewmodel property from the SelectionChanged event. That last one breaks your entire MVVM setup since the code behind of the view is now directly setting properties on the viewmodel.
Today I once again ran into this problem and decided to extend the LongListSelector to allow SelectedItem binding (note: I haven’t searched for an existing extended LongListSelector so it might as well exist somewhere else, this is just my attempt at it).
Create either a Windows Phone class library or a new class in a WP8 project, I called it ExtendedSelector and have it derive from LongListSelector, you’ll need to add a using statement for the Microsoft.Phone.Controls namespace.
- public class ExtendedSelector : LongListSelector
First we’ll need a dependency property
- public static readonly DependencyProperty SelectedItemProperty =
- DependencyProperty.Register("SelectedItem", typeof (object), typeof (ExtendedSelector), new PropertyMetadata(default(object)));
and the property that is set through the DP
- public new object SelectedItem
- {
- get { return GetValue(SelectedItemProperty); }
- set { SetValue(SelectedItemProperty, value); }
- }
Notice the “new” keyword on line 1? LongListSelector already has a SelectedItem property of type object, by using the new keyword we make the ExtendedSelector use our version of the property instead of the one from its base class
So now we have a property that can be bound to an object on our viewmodel, all there’s left to do now is set the actual selected item to the property. We do this by handling the SelectionChanged event, the event handler is hooked up in the constructor.
- public ExtendedSelector()
- {
- SelectionChanged += (sender, args) =>
- {
- SelectedItem = args.AddedItems[0];
- };
- }
And that’s it, we now have a LongListSelector with a bindable SelectedItem property
Multi-select
Let’s take it a step further, we want to enable multi-selection of items in our ExtendedSelector.
Start by adding another dependency property
- public static readonly DependencyProperty SelectionModeProperty =
- DependencyProperty.Register("SelectionMode", typeof (SelectionMode), typeof (ExtendedSelector), new PropertyMetadata(default(SelectionMode)));
- public SelectionMode SelectionMode
- {
- get { return (SelectionMode) GetValue(SelectionModeProperty); }
- set { SetValue(SelectionModeProperty, value); }
- }
SelectionMode is an enum containing three types of modes
- Single
- Multiple
- Extended
I only need single and multiple, so I’m not going to do anything with Extended. Change the constructor of the ExtendedSelector to this
- public ExtendedSelector()
- {
- SelectionMode = SelectionMode.Single;
- SelectionChanged += (sender, args) =>
- {
- if(SelectionMode == SelectionMode.Single)
- SelectedItem = args.AddedItems[0];
- else if (SelectionMode == SelectionMode.Multiple)
- {
- if (SelectedItem == null)
- {
- SelectedItem = new List<object>();
- }
- foreach (var item in args.AddedItems)
- {
- ((List<object>)SelectedItem).Add(item);
- }
- foreach (var removedItem in args.RemovedItems)
- {
- if (((List<object>) SelectedItem).Contains(removedItem))
- {
- ((List<object>) SelectedItem).Remove(removedItem);
- }
- }
- }
- };
- }
When the class is instantiated we default the SelectionMode to Single, when the property is set from Xaml the setter fires after the constructor, so this is a safe place to put that. Next in the event handler we check for the SelectionMode, if it’s set to Single, nothing changes. When set to Multiple we check if SelectedItem already contains items, if it does add the newly selected item to the list, if it doesn’t we’ll instantiate SelectedItem first as a List<object>. If there are any deselected items we remove them from the list.
And that’s it. A problem easily solved. I’m just hoping that the product team will actually include this functionality in the next SDK update so this post becomes obsolete.
Conclusion
This post is a quick fix for the LongListSelector so it supports binding to SelectedItem. If you want the complete class, grab it on GitHub
Update
Scott Lovegrove pointed out that the Windows Phone toolkit (http://phone.codeplex.com/ ) has a LongListMultiSelector, allowing for multiple item selection. It still doesn't have a bindable SelectedItem property but it should be pretty easy to make one like I did with the normal LongListSelector it his post.
This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.
Leave a Comment