Remember and navigate through multiple sets of state for a single page instance

image_pdfimage_print


   
  

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="CustomContentStateNavigationSample.StateNavigationPage" 
  xmlns:ns="clr-namespace:CustomContentStateNavigationSample">
  <DockPanel>
    <DockPanel.Resources>
      <ObjectDataProvider x:Key="usersDataSource" ObjectType="{x:Type ns:Users}"/>
      <DataTemplate x:Key="NameTemplate">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>
    <Button Name="removeBackEntryButton" DockPanel.Dock="Top" Click="removeBackEntryButton_Click" Height="25">Remove Back Entry</Button>
    <ListBox Name="userListBox" DockPanel.Dock="Top" Height="150" SelectionChanged="userListBox_SelectionChanged" DataContext="{StaticResource usersDataSource}" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ItemTemplate="{StaticResource NameTemplate}" />
    <ListBox Name="logListBox" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible"></ListBox>
  </DockPanel>
</Page>

//File:Window.xaml.cs
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Collections.Generic;
using System.Text;

namespace CustomContentStateNavigationSample
{
    public partial class StateNavigationPage : Page, IProvideCustomContentState
    {
        void removeBackEntryButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.NavigationService.CanGoBack)
            {
                JournalEntry entry = this.NavigationService.RemoveBackEntry();
                UserCustomContentState state = (UserCustomContentState)entry.CustomContentState;
                this.logListBox.Items.Insert(0, "RemoveBackEntry: " + state.JournalEntryName);
            }
        }

        internal void userListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if( e.RemovedItems.Count == 0 ) return;

            User previousUser = e.RemovedItems[0] as User;
            this.logListBox.Items.Insert(0, "AddBackEntry: " + previousUser.Name);

            UserCustomContentState userPageState = new UserCustomContentState(previousUser);
            this.NavigationService.AddBackEntry(userPageState);
        }

        CustomContentState IProvideCustomContentState.GetContentState()
        {
            User currentUser = this.userListBox.SelectedItem as User;
            this.logListBox.Items.Insert(0, "GetContentState: " + currentUser.Name);
            return new UserCustomContentState(currentUser);
        }
    }

    public class User
    {
        private string name;
        public User() { }
        public User(string name)
        {
            this.name = name;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
    [Serializable]
    class UserCustomContentState : CustomContentState
    {
        private User user;

        public UserCustomContentState(User user)
        {
            this.user = user;
        }

        public override string JournalEntryName
        {
            get
            {
                return this.user.Name;
            }
        }

        public override void Replay(NavigationService navigationService, NavigationMode mode)
        {
            StateNavigationPage page = (StateNavigationPage)navigationService.Content;
            ListBox userListBox = page.userListBox;

            page.userListBox.SelectionChanged -= page.userListBox_SelectionChanged;
            page.userListBox.SelectedItem = this.user;
            page.userListBox.SelectionChanged += page.userListBox_SelectionChanged;
        }
    }

    public class Users : ObservableCollection<User>
    {
        public Users()
        {
            this.Add(new User("A"));
            this.Add(new User("B"));
            this.Add(new User("C"));
            this.Add(new User("D"));
            this.Add(new User("E"));
            this.Add(new User("F"));
            this.Add(new User("G"));
        }
    }
}