I’ve been working on the fit and polish of my new WP8 app and wanted to preserve the selected items of a ListView
across page navigations. This allows the user to navigate to a new page to perform some action and return to the same state they left.
The first step to preserving and restoring state is to create a NavigationHelper
instance, and subscribe to the SaveState
and LoadState
events:
this.navigationHelper = new NavigationHelper(this); this.navigationHelper.LoadState += this.NavigationHelper_LoadState; this.navigationHelper.SaveState += this.NavigationHelper_SaveState;
Now you are notified when to save the page state and when to load it.
Saving Selected Indices
There are two ways to save selected items inside the SaveState
handler. The first is to assign the SelectedItems
property directly to a key in the PageState
property of the event argument. Inside the LoadState
handler, you would then reselect the items in the list.
Alternatively, you could save the index of each selected item. This will only work if you guarantee that items won’t change position, but it saves you from searching the collection for each item during the load.
To determine if an item at a given index is selected, you need to check the IsSelected property of the ListViewItem
instance. You can get a ListViewItem
for a given index using the method ContainerFromIndex:
private void NavigationHelper_SaveState(object sender, SaveStateEventArgs e) { List<int> selected = new List<int>(); for (int i = 0; i < this._list.Items.Count; i++) { if (((ListViewItem)this._list.ContainerFromIndex(i)).IsSelected) { selected.Add(i); } } if (0 < selected.Count) { e.PageState.Add("SelectedItems", selected); } }
Loading Selected Indices
Loading the indices is a little more difficult because the ListViewItem
instance may not be available when the LoadState
handler fires. Instead, you should use the LoadState
event to create a handler for the Loaded
event of your list.
In the Loaded
handler, you can then use the ContainerFromIndex
method to get the ListViewItem
of each saved index, and set the IsSelected
property to true:
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) { if (null != e.PageState && e.PageState.ContainsKey("SelectedItems")) { var list = (e.PageState["SelectedItems"] as List<int>); RoutedEventHandler handler = (object sender2, RoutedEventArgs e2) => { foreach (int index in list) { ((ListViewItem)this._list.ContainerFromIndex(index)).IsSelected = true; } }; this._list.Loaded += handler; } }
Now any selected items will be maintained as the user navigates to and from your page.