Tuesday, 16 August 2011

State management in Window Phone 7

In the previous article we’ve seen the Application execution model [Read here]. Now in this post I’ve created an example that would show how to persist the data from being lost when user moves forward and comes back to the application using the State collection by handling the NavigatedFrom and NavigatedTo  events.

Lets start, Open the visual studio 2010 and create new project. Now select the template for Silverlight Application for Windows Phone. and click ok.

Note: If you are new to Windows Phone and want to start with it. [Here] is the  post for how to start with Windows Phone 7 development.


To Create a UI in the MainPage.XAML file like below you need aTextBlock, a ListBox and a TextBox control. This application is to show the list of your favorite football players and selecting any player would show you the details of that player in the Textbox.

[Keeping things Little simpleWinking smile]

image

Here’s the markup for this UI

  1. <Grid x:Name="LayoutRoot" Background="Transparent">
  2.     <Grid.RowDefinitions>
  3.         <RowDefinition Height="Auto"/>
  4.         <RowDefinition Height="*"/>
  5.     </Grid.RowDefinitions>
  6.     <!--TitlePanel contains the name of the application and page title-->
  7.     <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
  8.         <TextBlock x:Name="ApplicationTitle" Text="Silveright Application" Style="{StaticResource PhoneTextNormalStyle}"/>
  9.         <TextBlock x:Name="PageTitle" Text="Sample App" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
  10.     </StackPanel>
  11.     <!--ContentPanel - place additional content here-->
  12.     <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  13.         <ListBox Height="191" HorizontalAlignment="Left" Margin="62,40,0,0" Name="listBox1"
  14.                 VerticalAlignment="Top" Width="297" >
  15.         </ListBox>
  16.         <TextBlock Height="30" HorizontalAlignment="Left" Margin="9,6,0,0" Name="textBlock1" Text="Favorite Football Players:" VerticalAlignment="Top" Foreground="#FF9EFF4B"></TextBlock>
  17.                     <TextBox Height="74" HorizontalAlignment="Left" Margin="-3,255,0,0" Name="textBox1" Text="" VerticalAlignment="Top" Width="440" />
  18.     </Grid>
  19. </Grid>

Now, create view model for this UI that’ll hold the data that would be displayed on it and will update itself when required.

  1. [DataContract]
  2. public class ViewModel : INotifyPropertyChanged
  3. {
  4.     private string textboxText1;
  5.     private Person selectedPerson; // for selection from the listbox
  6.     ObservableCollection<Person> personList;
  7.  
  8.     public ViewModel()
  9.     {
  10.         //populate some sample data
  11.         personList = new ObservableCollection<Person>()
  12.             {
  13.                 new Person(){Name="Syed Mehroz Alam", Age=10, City="Delhi", Country="India"},
  14.                 new Person(){Name="Zinedine Zidane", Age=20, City="Marseille", Country="France"},
  15.                 new Person(){Name="Ronaldinho", Age=30, City="Porto Alegre", Country="Brazil"},
  16.                 new Person(){Name="John Smith", Age=40, City="Washington", Country="USA"}
  17.             };
  18.     }
  19.  
  20.     #region Properties
  21.     [DataMember]
  22.     public ObservableCollection<Person> PersonList
  23.     {
  24.         get { return personList; }
  25.  
  26.         set { personList = value;
  27.         NotifyPropertyChanged("PersonList");
  28.         }
  29.     }
  30.  
  31.     [DataMember]
  32.     public Person SelectedPerson
  33.     {
  34.         get { return selectedPerson; }
  35.         set
  36.         {
  37.             selectedPerson = value;
  38.             NotifyPropertyChanged("SelectedPerson");
  39.         }
  40.     }
  41.  
  42.     [DataMember]
  43.     public string TextBoxText1
  44.     {
  45.         get
  46.         {
  47.             return textboxText1;
  48.         }
  49.         set
  50.         {
  51.             textboxText1 = value;
  52.             NotifyPropertyChanged("TextBoxText1");
  53.         }
  54.     }
  55.     #endregion
  56.  
  57.     public event PropertyChangedEventHandler PropertyChanged;
  58.  
  59.     private void NotifyPropertyChanged(string property)
  60.     {
  61.         if (PropertyChanged != null)
  62.         {
  63.             PropertyChanged(this, new PropertyChangedEventArgs(property));
  64.         }
  65.     }
  66.  
  67. }
  68.  
  69. [DataContract]
  70. public class Person
  71. {
  72.     [DataMember]
  73.     public string Name { get; set; }
  74.     [DataMember]
  75.     public int Age { get; set; }
  76.     [DataMember]
  77.     public string City { get; set; }
  78.     [DataMember]
  79.     public string Country { get; set; }
  80. }

In the view model the selectedPerson property is created to keep the user’s selection in from listbox. The selected item’s details would be shown to the text box. Now bind the UI controls with the view model. Keep the DataContract and DataMember attribute on the Class and its members that needs to be save in the State collection. This will help in serialization of data. Now bind the ViewModel with the UI Main.XAML

  1. <ListBox Height="191" HorizontalAlignment="Left" Margin="62,40,0,0" Name="listBox1"
  2.                     ItemsSource="{Binding PersonList}"
  3.                 DisplayMemberPath="Name" SelectionChanged="listBox1_SelectionChanged"
  4.                 SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" VerticalAlignment="Top" Width="297" >
  5.             </ListBox>
  6.             <TextBox Height="74" HorizontalAlignment="Left" Margin="-3,255,0,0" Name="textBox1" Text="{Binding TextBoxText1, Mode=TwoWay}" VerticalAlignment="Top" Width="440" />
  7.            

Now everything is set for the sample application. As per the Application execution model we have to handle the NavigatedTo and NavigatedFrom event with checking if user is launching the application first time or if user is coming back and keeping the track when user navigates away from the application. In case user navigates away from the page the NavigatedFrom save the ViewModel instance to state collection. In case user returns back use the custom boolean flag isNewPageInstance that would be true when the page constructor get executed. Based on that we’ll create new ViewModel instance otherwise retrieve the saved ViewModel from the State Collection if exists. Here’s the complete code for the MainPage.XAML.cs file.

  1. public partial class MainPage : PhoneApplicationPage
  2.     {
  3.         ViewModel viewModel;
  4.         bool isNewPageInstance = false;
  5.  
  6.         // Constructor
  7.         public MainPage()
  8.         {
  9.             InitializeComponent();
  10.             isNewPageInstance = true;
  11.         }
  12.  
  13.         protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  14.         {
  15.             base.OnNavigatedTo(e);
  16.  
  17.             if (isNewPageInstance)
  18.             {
  19.                 if (viewModel == null)
  20.                 {
  21.                     if (State.Count > 0)
  22.                     {
  23.                         viewModel = (ViewModel)State["ViewModel"];
  24.                     }
  25.                     else
  26.                     {
  27.                         viewModel = new ViewModel();
  28.                     }
  29.                 }
  30.                 DataContext = viewModel;
  31.             }
  32.             isNewPageInstance = false;
  33.         }
  34.  
  35.         protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  36.         {
  37.             base.OnNavigatedFrom(e);
  38.             if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
  39.             {
  40.                 State["ViewModel"] = viewModel;
  41.             }
  42.         }
  43.  
  44.     }
Now handle the List selection changed event and update the textbox accordingly.
  1. private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2. {
  3.     Person selectedPerson = (Person)listBox1.SelectedItem;
  4.     textBox1.Text = selectedPerson.Name.Split(' ')[0] + ", " + selectedPerson.Age + ", " + selectedPerson.City + "," + selectedPerson.Country;
  5. }

Now start the application and select any person from the list

image
Now press Start button from the Phone.
image
It will navigates away from the application letting it into the Dormant start now do something let say launch some other application
now press back button to get back to the application.
image
It’ll show you the last selection that you have made. Smile
Download the source code for this article
   


No comments:

Post a Comment