I’m excited to announce that I will be making available a class library I’ve been developing and using personally in my work. I will be maintaining this library and adding new controls and components as I deem them stable enough for others to use. For the first release, there will only be three controls geared towards lists presentation but I think it will be helpful to a lot of WP WinRT devs out there nonetheless.

Download QKit

The class library is a toolkit that will augment your development experience by providing implementations for complicated or commonly used in-app experiences. This is not meant to replace any other toolkits out there but, rather, to complement them. This toolkit will be available via Nuget and it is currently limited to only Windows Phone’s WinRT platform. You can search for this toolkit under the name “QKit” or by running “Install-Package QKit” in the Nuget package manager console.

What’s Included?

ListPlaceholder

The first, and most simple of the controls that are available is the ListPlaceholder control. For a good user experience, an empty list should let the user know why it is empty using a short bit of text rather than a blank screen. Something like the following screenshot or the leading image:

With the ListPlaceholder control, you can place it anywhere on page (I recommend underneath the ListView or GridView you want it to work against in the same container) and point it to a ListViewBase control.

For example, let’s say I have a completed ListView. Naturally, it’s sitting in some panel. For my case, it’s in a Grid.

<Grid> <ListView x:Name="MyList" /> </Grid>

The first thing we need to do is drop in our new ListPlaceholder control and then point the ListPlaceholder control to the list we want to show and hide against when it’s empty.

<Grid> <q:ListPlaceholder ListTarget="{Binding ElementName=MyList}" /> <ListView x:Name="MyList" /> </Grid>

Don’t forget to add the namespace for QKit in order to use this control. I’ve added it as “q” for brevity.

<Page ... xmlns:q="using:QKit"> ... </Page>

By default, the ListPlaceholder control will show a “Loading…” message when ItemsSource of the list is null and a “Nothing to show” message when ItemsSource is not null but the list is still empty. You can change these two messages using the LoadingPlaceholderContent and the EmptyPlaceholderContent properties to show custom messages or even custom displays using their corresponding template properties. Let’s see how we can set it to show our own custom message when the list is empty.

<Grid> <q:ListPlaceholder ListTarget="{Binding ElementName=MyList}" LoadingPlaceholderContent="Looking for stuff, hang tight..." EmptyPlaceholderContent="Nothing to see here... move along." /> <ListView x:Name="MyList" /> </Grid>

Finally, if you don’t want the control to automatically decide which content to show (loading vs empty), you can set or bind the PlaceholderMode property to manually tell it which to show when the list is empty.

By now, we should be accustomed to implementation of SemanticZoom to create a JumpList in WP8.1. However, our implementation can get cumbersome and complicated because it’s composed of many different parts. Furthermore, our latest attempt at making the perfect JumpList came a little short since the AlphaJumpList still doesn’t work properly in landscape orientation. Well, I’m happy to say that all of our woes are now solved with my new GenericJumpList and AlphaJumpList controls.

Why should you migrate over to these controls rather than using the SemanticZoom/ListView combo? I’ve already mentioned the first reason and that reason was that it now works in landscape without any additional work after dropping it in and wiring it up. The next reason is because, now, the controls are a simple drop in and wraps around any standard ListView or GridView to turn it into a JumpList. This lets anyone convert existing lists in their apps to JumpList should they feel like it’s appropriate to do so. The last reason is because these two controls have performance considerations built in. I’ve included any required performance improvements needed for conventional usage.

Enough talk, let’s see how we can incorporate these controls into our existing lists. Let’s go back to our simple list example:

<Grid> <ListView x:Name="MyList" ItemsSource="{Binding MyItems}" /> </Grid>

Currently it’s just a ListView with its ItemsSource bound to a flat list. The first thing you need to do is group the items so it’s no longer a flat list. This is easy since the JumpListHelper class is included in QKit.

// Using extension method var MyGroupedItems = MyItems.ToAlphaGroups(x => x.DisplayValue); // or using static method var MyGroupedItems = JumpListHelper.ToAlphaGroups(MyItems, x => x.DisplayValue);

The helper class will spit back a list of JumpListGroups that is compatible with the Generic and AlphaJumpLists. For demonstration purposes, I’ll expose the grouped items as a different property but you can just return the list of JumpListGroups in place of your flat list. Note that the grouped items no longer have to be in a CollectionViewSource. The JumpList controls will take care of that for you. Just a list of JumpListGroups is enough.

<Grid> <ListView x:Name="MyList" ItemsSource="{Binding MyGroupedItems}" /> </Grid>

Now, the last step is to simply wrap the ListView or GridView control with a JumpList control. That’s it. The control will take care of the rest.

<Grid> <q:AlphaJumpList> <ListView x:Name="MyList" ItemsSource="{Binding MyGroupedItems}" /> </q:AlphaJumpList> </Grid>

Without going into too much detail, the JumpList controls pretty much hijacks the ItemsSource of the ListView and calls it its own. From there, it wraps that ItemSource into a CollectionViewSource automatically if it’s not already, and then modifies the ListView to look at CollectionViewSource and adds the appropriate group styles. Of course the JumpList controls automatically handles the SemanticZoom stuff so we don’t have to anymore.

Note: If the child ListViewBase’s ItemsSource is being set programmatically rather than through data binding, you need to call the ReleaseItemsSource method before setting the ListViewBase’s ItemsSource, and the ApplyItemsSource method after setting the ListViewBase’s ItemsSource on the JumpList control.

Why?

A few questions people might have that I want to address.

Q: First, why are you doing this?

A: Well, people have been having issues or missing certain steps when implementing my tutorial for JumpLists. I do not blame anyone. It is kind of complicated especially when you have to implement it over several areas or several apps. Also, packaging it into a class library lets me make it more complicated behind the scenes without hindering any developers while addressing issues like the orientation limitation.

Q: Why do the GenericJumpList and AlphaJumpList controls need a ListViewBase as a content rather having it built in as part of the control like LongListSelector in SL8.0?

A: This one was tough because I wanted to do something like the LongListSelector but I didn’t want to reimplement all of the events and properties of a ListViewBase like ItemClick or ItemTemplate. If I had derived from ListViewBase, I wouldn’t have to do that but then I couldn’t use a SemanticZoom control and a SemanticZoom is needed to create a JumpList experience. My solution was to let developers design using a ListView or GridView since they are probably comfortable and well versed in doing that. Then, let developers just wrap those ListViews and GridViews with my control for minimal code change. This also has the added benefit of exposing the ListViews and GridViews for events and property modifications and it even works with the ListPlaceholder control!

Q: Can I change the looks of the control?

A: Yes, they are templated custom controls. I’ve included the Generic.xaml file so you can peruse the styles and templates being used so you can adapt them to make it your own. I do have to say that I’ve spent many hours styling these controls to look as correct as possible so consider leaving them be if you want your app to look clean and proper.

Q: What if it breaks or doesn’t work with my code?

A: Well, you’re free to contact me either on this post or reach out to me at QDev@live.com for to notify me of any bugs but since this is a side project, I cannot guarantee timeliness in any fixes. I will eventually making the source code available so anyone can modify the code and fix any issues for themselves in their personal uses.