Share a Generic XAML ListView, ItemsSource, and DataTemplate with UserControls in Windows Universal Apps

This post applies to Windows Universal Apps specifically. These techniques probably won’t work with WPF or Windows 8/8.1 Apps because the XAML hierarchy and namespaces are different.

The title is certainly a mouthful, but stick with me to understand where this scenario can be useful.

Let’s say you want to re-use a ListView without copy and pasting everything about it wherever you need it. Simple enough, right? Just put it in a UserControl! Not so fast. What if you want to define the ListView’s ItemsSource from one level above the UserControl? It gets a little more complicated. This is especially true if you want to take advantage of a VisualStateManager with the ListView’s ItemTemplate.

CustomListView

For example, I had a UserControl which allowed users to scroll left/right on a ListView by clicking buttons left/right instead of using a scrollbar. I wanted to share this ListView in multiple places,  but didn’t want to restrict the UserControl to a single ItemsSource by hard coding it in the UserControl itself. I wanted to “pass in” the ItemsSource and DataTemplate to define the layout of the items from one level above the UserControl. Additionally, I wanted the layout to change based on the width of the screen to work with phones, tablets, and wide layouts.

So here’s what I did after a few hours of struggling through wildly varying documentation across WPF, Windows 8/8.1, and Windows Universal Apps.

Creating the DataTemplate UserControl

We first need to define the lowest level of the chain to determine what and how the data will be displayed in each data bound ListViewItem. We put the XAML in a separate UserControl so that we can also attach a VisualStateManager to the ListViewItem and have it re-organize appropriately on different layout sizes.

This UserControl will then be referenced one level up in the DataTemplate of the main UserControl which contains the ListView and the left/right Buttons.

Before we can go to the next step, we need to add some code to the code behind. The code above assumes that some property called “LiveLeagueGame” exists. Since this UserControl will be used in the DataTemplate of each ListViewItem, we need to bind that property to the UserControl’s DataContext. We also subscribe to the DataContextChanged event so that we can update all data bindings appropriately.

Creating the Main UserControl

Next we need to create the UserControl which will contain the ListView and buttons to manipulate the scrolling of that ListView.

Take notice of the two data binding statements which make this work properly. ItemsSource="{x:Bind ItemsSource}" and ItemTemplate="{x:Bind ItemTemplate}"> . Both are bound to Dependency Properties on the UserControl’s “code behind”. We will set these properties from above and have them bound to the ListView at the appropriate time. This will allow us to “pass in” the ItemsSource and ItemTemplate from a level up without having to hard code them in to the UserControl itself.

In the code behind, we need to create the Dependency Properties that will be bound in the above XAML.

Creating the DataTemplate to “Pass In”

Because we want to be able to “pass in” the DataTemplate to be used in our UserControl’s ListView collection, we need to define the DataTemplate as a StaticResource. This DataTemplate will contain nothing more than our first UserControl created above. This way each ListViewItem will have this DataTemplate bound to it and display by however it is defined in the UserControl.

Putting It All Together

The last step is to tie everything together by using our UserControl in whatever Page we want to display. We will bind our ItemsSource to an ObservableCollection (this is passed down into the UserControl’s ListView) and bind the ItemTemplate to our StaticResource (this also gets passed down into our UserControl’s ListView).

 

Comments 1

  • Hi,
    Great job, i’m looking for an a user control like this. Could you explain me the button behaivour?

    How do you calculate the scroll offset?

    Thanks for your help.

Leave a Reply

Your email address will not be published. Required fields are marked *