Good news! The ListView control allows multiple selection with proper styling out of the box. The bad news? You can’t tap on the left edge of the item to activate it like you can in the email or messaging app. Also, if you haven’t noticed, the animation that shows the checkboxes are horrid. The great news? I’ve created a control to solve those issues (until Microsoft decides to release a toolkit that solves the same issue).
The MaterialCODEPLEX – view source + contribute
NUGET – download and use
Veteran Windows Phone users will know that whenever they see the option to do multiple selection in the AppBar, most likely there they can tap on the left edge of any item in a list to select it and bring up all of the checkboxes to select more afterwards. One of the first ListView limitation I noticed when moving to WPRT is that while multiple selection is there, you can’t activate it by tapping on the left edge like you can in the LongListMultiSelector.
You can, however, programmatically put it into multiple selection mode where you’ll see a bland, and frankly, terrible slide in animation that will show all of the multiple selection checkboxes. Almost every single animation in Windows Phone operates on some kind of easing so it is natural and fluid. This is true not only for the native experience found throughout the OS but also for almost all of the shipped WPRT controls… All except, of course, for the animation that transition a ListView into multiple selection mode.
The MultiSelectListView is basically a ListView with a retemplated ListViewItemContainerStyle and some added event handling. The new ListViewItemContainerStyle has an additional component called the EdgeSelectButton that switches the MultiSelectListView’s SelectionMode. This button is what allows you to tap the left edge to enable multiple selection.
I actually spent a good amount of time on the EdgeSelectButton despite being such a simple component. Just believe me when I say that the animation for the pressed state is nearly identical to the native counterpart. Not only that, I matched the native visual and touch target sizes for the best experience. The visual feedback of the EdgeSelectButton only takes up 15px horizontally so it doesn’t touch the ListViewItem just like the native version. But 15px is way too slim to guarantee a pleasant experience using touch. That’s why my EdgeSelectButton and the native version has an invisible touch target overhang that makes it effectively 45px wide. This is the red square in the picture above. After it’s pressed, the ListViewItems and the hidden checkboxes slide in while the EdgeSelectButton fades out with a dramatic animation curve that is nearly identical to the native experience. It’s hard to get it just right but I think I’ve come close enough to please most picky devs and users.
Additional to the please UX, the MultiSelectListView also handles the back button press to leave multiple selection mode automatically and I’ve also added a SelectionModeChanged event. The new event is something that I was surprised to find out that was missing from the ListView control. It’s triggered every time the SelectionMode property changes and it’s a great way to watch when the user activates multiple selection mode by tapping on the left edge of an item.
What Did I Break?
The unfortunate news for anyone using my AlphaJumpList or GenericJumpList controls is that I had to modify some margins for the header templates. I had to add 19px left margin to the header templates and remove the 19px left padding on the JumpList controls themselves. Effectively, the headers will not change and will look like the same way before this update. What you will notice is every ListView item in a JumpList will shift to the left. The fix for this is just to add a left margin of 19px to the affect item templates. JumpLists using the new MultiSelectListView will not have this issue since the EdgeSelectButton will account from this 19px change. Sorry :).
There’s one thing that I can’t seem to figure out that I’m hoping someone can shed a light on. Right now, the handling of the back button press is not ideal. Most WP8.1 apps will be using the NavigationHelper class in the shipped project templates. Unfortunately, the NavigationHelper hooks into the back button pressed event upon app start by default. This means that I cannot handle the back button press since the NavigationHelper will handle it first. So by the time my logic to handle the back button press, the NavigationHelper has already handled it first and invoked the go back command and thus preventing me from stopping page navigation so I can deal with my MultiSelectListView.
Currently, I’m just traversing the visual tree to get to the Frame and canceling navigation instead. This works for page navigation but it doesn’t work for any other case. For example, if the MultiSelectListView is in the multiple selection mode and is hosted in a popup or flyout, the first back button press should, ideally, revert the MultiSelectListView to a no selection mode. Instead, the back button just closes the popup or flyout and the MultiSelectListView remains in multiple selection mode. Obviously, there must be some not well known way of handling the back button press first before anything else gets to it to handle transient UI or control states where returning to default state is expected. The ComboBox is such a control that does this along as well as any popup control. Until a solution is found, this is the best I can do for now.