Jumping through hoops with the JumpViewer
Windows 8^HDeveloper Preview is out, yay !
And with it, comes a whole lot of new toys to play with : Visual Studio 11, Blend 5, but most important : the Metro Ui goodness is also available for desktop developers to play with !
And along with new shiny Ui’s come new paradigms, new API’s, and new User controls.
The one we’re going to have a look today is the JumpViewer : a new control that works a little bit like a Master-Detail view, only there is only one view shown at once, and the user can Switch back and forth by tapping master items and “zoom-pinching out” the detail view.
Okay, enough for the concept, after all, there is a whole lot of videos around from the latest Build conference : What we are interested in is how we will actually code an app that uses our new toy.
The usual way to go is to take microsoft’s examples, look how they’ve done it, mimic, copy, paste, adapt, smile, and voilà : you know everything about your new friend.
Only this time, I wasn’t exactly thrilled by the way Microsoft had set up their example :
For those who don’t know the JumpViewer : there are two views : one called JumpView, the other ContentView.
In microsoft’s example, which you can find here, the ContentView’s ItemsSource was bound to a CollectionViewSource, using a regular data binding, but the JumpView’s – the master, if you will – was simply not even set. A little bit of investigation will show that the ItemSource property is set in the codebehind, and in my book, that spells code smell.
So, from there, how would we make it MVVM friendly ?
My first attempt was to try to use the exact same binding on the JumpView. It required creating a Template for the Group items, and collapse the Items themselves. Unfortunately, it seems the internals of the JumpViewer control bases its navigation between the two views on the collectionView’s CollectionGroups. To make it simple : the item clicked in the JumpView must be the group of the ContentView, in order to navigate to it.
Therefore, using the same binding for both views would not expose such hierarchy, and even though the visual result would be OK, the navigation would not work.
The second attempt was to edit the binding to provide an additional Path in the JumpView’s binding in order to try an reach the CollectionGroups, but for some reason, the CollectionGroups was never reached. Adding a converter to allow us to set a breakpoint in the middle of the binding was also a failure : The breakpoint was never hit, meaning that the binding could not reach the CollectionGroups.
Reverting to the same binding as in the ContentView with the DebuggerConverter still applied to the binding would show that the passed value, the CollectionViewSource, was a Windows Runtime object. In other words : a COM object. I can only guess that the CollectionGroups was lost in the marshalling of the system object.
The third and last approach was to use a ValueConverter for the JumpView’s binding : since the CollectionGroups property was not reachable through a binding, but was reachable, after an explicit cast in C#, it was then a no-brainer : we could use a ValueConverter to join the dots and return the CollectionGroups property that was not accessible with a plain binding. The converter would then look like this:
publicclassGroupedCollectionToGroupsCollectionConverter : IValueConverter
publicobject Convert(object value, string typeName, object parameter, string language)
publicobject ConvertBack(object value, string typeName, object parameter, string language)