Synchronizing Collections in Windows Store Apps

One issue that often comes up when building WSAs is managing selection in your filled/snapped/full screen views.  The goal, of course, is to provide a reasonable view as the user snaps your application which is often done by providing two UIs within the page – one with a GridView for filled or full screen and the second with a ListView for snapped view.  You hide and show the two views using the Visual State Manager when using the normal templates.

If selection is provided, then ideally it would be carried over when changing views – this actually isn’t hard – it can certainly be done manually and if you only allow a single selection it’s dead easy even with MVVM.  Multi-selection is a bit trickier.  Enter the SynchronizedCollectionBehavior in MVVMHelpers.  It allows the UI to bind a collection of “selected items” to a collection in the ViewModel – so the ViewModel can track and alter the selection, but more importantly you can bind it to multiple UI things and they all track the same selection automatically.

There are two ways to activate the behavior – first is through the normal Blend framework –

 

<ListView ItemsSource="{Binding Names}" SelectionMode="Multiple" HorizontalAlignment="Stretch" Margin="20">
    ...            
    <Interactivity:Interaction.Behaviors>
       <Interactivity1:SynchronizedCollectionBehavior 
                  Collection="{Binding SelectedNames}" />
    </Interactivity:Interaction.Behaviors>
</ListView>

Here the ViewModel is exposing an ObservableCollection of names (called SelectedNames) to manage the selected items. The actual collection (also string names) is just Names:

public IReadOnlyList<string> Names { get; private set; }
public IList<string> SelectedNames { get; private set; }

public MainViewModel()
{
    Names = new List<string>
                {
                    "Alice", "Bob", "Carol", "David", "Edgar", "Frank",
                    "Georgia", "Hank", "India", "Jack", "Karen", "Larry",
                    "Mike", "Nate", "Oscar", "Peter", "Quix", "Russ", "Steve",
                    "Tonya", "Uma", "Violet", "Walter", "Xi", "Yvonne", "Zed"
                };
    SelectedNames = new ObservableCollection<string>();
   ...
}

The second activation mechanism is through a normal attached property –

<GridView ItemsSource="{Binding Names}" Grid.Column="1"  Grid.Row="1"
          SelectionMode="Extended" HorizontalAlignment="Stretch" Margin="20"
          Interactivity1:SynchronizedCollectionBehavior.IsEnabled="{Binding SelectedNames}">

This performs exactly the same action but allows it to be done as an attribute.

Here is a test program which shows connecting it up to multiple ItemsControls and even changing the selection styles between them.

SynchronizedList

About Mark Smith

Windows systems developer with low-level operating system, threading and .NET experience. For the past several years I have been involved with WPF/Silverlight and most recently iOS and Android. I have worked as an architect and designer for several companies and am particularly interested in client/server and graphical solutions. Specialties:.NET, WPF, Silverlight, Windows, iOS