Home > C#, MVVM, WinRT > Using IncrementalUpdateBehavior to incrementally show data in ListViewBase controls

Using IncrementalUpdateBehavior to incrementally show data in ListViewBase controls

15/01/2014

In Windows 8.1 Store apps, a great work has been done to improve the responsiveness of ListViewBase controls (i.e., GridView and ListView) when we have to show large amount of data items. In particular, the item display experience is enriched through placeholders and incremental data template updates, as we can read on MSDN.

However, the ContainerContentChanging event (presented in the above article) has a drawback. Its working strictly depends on the structure of data template: we need to use XAML elements name to update the properties. So, it introduces an heavy dependency between the UI and the code-behind, and thus it is impossible to use it, for example, with MVVM.

In such situations, the Behavior SDK can help us. It provides the IncrementalUpdateBehavior that, as we can read in the documentation:

Allows incremental updating of ListView and GridView contents to support faster updating. By attaching this behavior to elements in the ItemTemplate used by these views, some of the updates can be deferred until there is render time available, resulting in a smoother experience.

Its usage is straightforward, because we only need to specify, for each object in the template, the relative priority for the incremental update (lower values are shown first). So, let’s see how to use it in a Windows Store app built using MVVM Light.

We have the following ViewModel, in which we create 100,000 instance of a Person class (we use such a large number to make the problem clear):

public class MainViewModel : ViewModelBase
{
    private void CreatePeopleList()
    {
        for (int i = 1; i <= 100000; i++)
        {
            if (i % 2 == 0)
            {
                People.Add(new Person
                {
                    Index = i,
                    FirstName = "John",
                    LastName = "Doe",
                    ImageUri = new Uri("ms-appx:///Assets/Male.png")
                });
            }
            else
            {
                People.Add(new Person
                {
                    Index = i,
                    FirstName = "Jane",
                    LastName = "Doe",
                    ImageUri = new Uri("ms-appx:///Assets/Female.png")
                });
            }
        }
    }

    public List<Person> People { get; set; }

    public MainViewModel()
    {
        People = new List<Person>();
        this.CreatePeopleList();
    }
}

This ViewModel is assinged to the DataContext property of the MainPage, that uses a GridView to show the data:

<GridView ItemsSource="{Binding People}"
          SelectionMode="None">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Height="100" Width="100" 
                        Background="Blue">
                <TextBlock Text="{Binding FirstName}" 
                           Foreground="Yellow" />
                <TextBlock Text="{Binding LastName}" 
                           Foreground="Aqua" />
                <TextBlock Text="{Binding Index}" 
                           Foreground="LightGray" />
                <Image Source="{Binding ImageUri}" />
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

If we run the app and quickly scroll the list, we’ll see a sort of flickering effect while new elements are shown. This happens because Windows 8.1 entirely loads all the parts of each element before passing to the next one.

We can obtain a better user experience if these parts are loaded incrementally, i. e., first the name of all the visible items, then the image and lastly the index. As we have said before, this task is very easy to accomplish, because we just need to add an IncrementalUpdateBehavior to each object in the template, setting its Phase property in the right way:

<GridView ItemsSource="{Binding People}"
          SelectionMode="None"
          ShowsScrollingPlaceholders="False">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Height="100" Width="100" 
                        Background="Blue">
                <TextBlock Text="{Binding FirstName}" 
                           Foreground="Yellow">
                    <i:Interaction.Behaviors>
                        <core:IncrementalUpdateBehavior Phase="1"/>
                    </i:Interaction.Behaviors>
                </TextBlock>
                <TextBlock Text="{Binding LastName}" 
                           Foreground="Aqua">
                    <i:Interaction.Behaviors>
                        <core:IncrementalUpdateBehavior Phase="1" />
                    </i:Interaction.Behaviors>
                </TextBlock>
                <TextBlock Text="{Binding Index}" 
                           Foreground="SaddleBrown">
                    <i:Interaction.Behaviors>
                        <core:IncrementalUpdateBehavior Phase="3" />
                    </i:Interaction.Behaviors>
                </TextBlock>
                <Image Source="{Binding ImageUri}">
                    <i:Interaction.Behaviors>
                        <core:IncrementalUpdateBehavior Phase="2" />
                    </i:Interaction.Behaviors>
                </Image>
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

It’s time to run the app again. Now the scrolling appears smoother, as the parts of the template are updated in the order specified by the Phase property: first, the names (FirstName and LastName) of all the items, then all the images and finally all the indexes.

Categories: C#, MVVM, WinRT
  1. Maxim
    16/01/2014 at 05:47

    Hi Marco,
    Would it work if in DatataTemplate I’ll use UserControl with Children inside, like at your sample?

  1. 15/01/2014 at 11:07
  2. 28/01/2014 at 04:49
Comments are closed.
%d bloggers like this: