导出 (0) 打印
全部展开
信息
您所需的主题如下所示。但此主题未包含在此库中。

如何保留和还原 Windows Phone 8 的页面状态

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

在 Windows Phone 中,当用户向前导航离开应用时,应用通常会处于休眠状态。在休眠状态中,将停止执行应用代码,但应用仍完好地保留在内存中。如果应用处于休眠状态并且用户导航回应用,则应用会继续,并且应用中每页的状态将会自动还原回用户导航离开前的状态。

但是,在用户导航离开后,应用可能会被逻辑删除。在这种情况下,应用不会保存在内存中,但是将会存储一些有关应用的信息 - 对于本主题而言,最重要的是存储 PhoneApplicationPage 对象的状态字典。如果用户导航回已经逻辑删除的应用,则应用应使用存储在状态字典中的数据还原页面状态,以便页面所处的状态看上去与用户导航离开时的状态相同。此过程主要包括将页面上的任何控件值设置为逻辑删除应用前的最后值。

本主题演示如何使用数据绑定轻松保存和还原页面用户界面的状态。 有关逻辑删除以及应用如何在整个生命周期内管理状态的更多信息,请参见 Windows Phone 8 的应用激活和停用

本主题包括以下部分。

 

下列步骤演练如何创建一个在取消激活和重新激活时保存并还原多个控件的状态的应用。

创建保留其用户界面状态的应用

  1. 在 Visual Studio 中创建新的 Windows Phone 应用  项目。此模板在“Windows Phone”类别中。

  2. 向 MainPage.xaml 中添加一些基本控件。在此示例中,使用 TextBoxCheckboxSliderRadioButton 控件。某些更为复杂的控件将会在以后的章节中讨论。

    在下面的 XAML 代码中,每个控件都具有一个使用 Binding 关键字的属性。这些就是将在应用生命周期中保存和还原的控件属性。对于 TextBox 控件,将绑定 Text 属性。对于 Slider 控件,将绑定 Value 属性。对于 RadioButtonCheckBox 控件,将绑定 IsChecked 属性。Binding 关键字后面的术语(如“Slider1Value”)是控件绑定到的字段名称。这些字段将在本演练的下一个步骤中定义。绑定表达式的最后部分“Mode=TwoWay”表示绑定应该是双向绑定。换言之,如果控件绑定到的字段发生更改,则控件将会更新。如果控件的值发生更改,则绑定字段将会更新。

    在 MainPage.xaml 文件中,将以下 XAML 代码放置在名为“ContentPanel”的 Grid 元素中。

    <TextBox Text="{Binding TextBox1Text, Mode=TwoWay}" Height="72"
     HorizontalAlignment="Left" Margin="20,20,0,0" Name="textBox1"
     VerticalAlignment="Top" Width="440" />
    <CheckBox IsChecked="{Binding CheckBox1IsChecked, Mode=TwoWay}"
     Content="CheckBox" Height="71" Name="checkBox1" Margin="20,100,0,0"
      VerticalAlignment="Top"/>
    <Slider Value="{Binding Slider1Value, Mode=TwoWay}" Height="84" Name="slider1"
     Width="440" Margin="20,180,0,0"  VerticalAlignment="Top"/>
    <RadioButton IsChecked="{Binding RadioButton1IsChecked, Mode=TwoWay}"
     Content="RadioButton 1" Height="71" Name="radioButton1"
     GroupName="RadioButtonGroup"  Margin="20,260,0,0" VerticalAlignment="Top"/>
    <RadioButton IsChecked="{Binding RadioButton1IsChecked, Mode=TwoWay}"
     Content="RadioButton 2" Height="71" Name="radioButton2" 
    GroupName="RadioButtonGroup"  Margin="20,340,0,0" VerticalAlignment="Top"/>
    
    
  3. 接下来,添加一个类,以便包含与 XAML 中所定义的控件绑定的字段。 从 Visual Studio 的“项目”菜单中,选择“添加类……”。在项目列表中选择要添加的“类”,并在“名称”字段中键入 ViewModel.cs。单击“添加”,将类添加到项目中。

  4. 在该文件的顶部,添加序列化和 ComponentModel 命名空间的 using 指令,这些指令可以分别为序列化和数据绑定提供支持。

    using System.Runtime.Serialization;
    using System.ComponentModel;
    
    
  5. 在 ViewModel.cs 文件中,在类定义前添加 DataContract 属性。此属性表示在序列化和反序列化操作中 DataContractSerializer 将使用该类。保存在 PhoneApplicationPageState 属性中所有数据(正如此类)必须是可序列化的数据协定。有关此序列化类型的更多信息,请参见使用数据协议

    还应声明该类实现 INotifyPropertyChanged 接口。该接口允许用户界面控件在绑定数据发生更改时自动更改其值。

    [DataContract]
    public class ViewModel : INotifyPropertyChanged
    {
    }
    
    
  6. 在类中为每个绑定的控件属性添加私有成员变量。

    private string _textBox1Text;
    private bool _checkBox1IsChecked;
    private bool _radioButton1IsChecked;
    private bool _radioButton2IsChecked;
    private double _slider1Value;
    
    
  7. 接下来,向类中添加 INotifyPropertyChanged 功能。这包括添加 PropertyChanged 事件和实现称为 NotifyPropertyChanged 的方法,该方法将引发 PropertyChanged 事件。

    public event PropertyChangedEventHandler PropertyChanged;
    
    private void NotifyPropertyChanged(string propertyName)
    {
      if (null != PropertyChanged)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    
    
  8. 接下来,为每个绑定的控件属性添加公共属性。请注意,这些属性名称是在 XAML 文件的 Binding 表达式中使用的名称。 对于每个属性,get 访问器仅返回对应私有成员变量的值。put 访问器设置成员变量的值,并调用 NotifyPropertyChanged,从而有效地通知对应控件应该更新其值。每个属性还会标记有 DataMember 属性以让序列化程序获知该属性应该序列化。

    将下面的代码粘贴到 ViewModel 类定义中。

    [DataMember]
    public string TextBox1Text
    {
      get { return _textBox1Text; }
      set
      {
        _textBox1Text = value;
        NotifyPropertyChanged("TextBox1Text");
      }
    }
    
    [DataMember]
    public bool CheckBox1IsChecked
    {
      get { return _checkBox1IsChecked; }
      set
      {
        _checkBox1IsChecked = value;
        NotifyPropertyChanged("CheckBox1IsChecked");
      }
    }
    
    [DataMember]
    public double Slider1Value
    {
      get { return _slider1Value; }
      set
      {
        _slider1Value = value;
        NotifyPropertyChanged("Slider1Value");
      }
    }
    
    [DataMember]
    public bool RadioButton1IsChecked
    {
      get { return _radioButton1IsChecked; }
      set
      {
        _radioButton1IsChecked = value;
        NotifyPropertyChanged("RadioButton1IsChecked");
      }
    }
    
    [DataMember]
    public bool RadioButton2IsChecked
    {
      get { return _radioButton2IsChecked; }
      set
      {
        _radioButton2IsChecked = value;
        NotifyPropertyChanged("RadioButton2IsChecked");
      }
    }
    
    
  9. 保留 UI 状态的最后步骤是处理代码隐藏文件中页面状态的更改。在 MainPage.xaml.cs 中,将下列成员变量添加到 MainPage 类定义中。第一个变量的类型为 ViewModel。这是以前步骤中创建的类,将存储 UI 控件的值。 第二个变量是称为 _isNewPageInstance布尔值。稍后将使用该变量确定页面是新实例(如当首次启动应用或逻辑删除后重新启动时)还是现有实例(如当用户向后导航到应用中的页面时)。

    public partial class MainPage : PhoneApplicationPage
    {
      ViewModel _viewModel;
      bool _isNewPageInstance = false;
    
    
  10. 在页面构造函数中,将 _isNewPageInstance 设置为 true

    // Constructor
    public MainPage()
    {
      InitializeComponent();
    
      _isNewPageInstance = true;      
    }
    
    
  11. 接下来,重写从基 Page 类继承的 OnNavigatedFrom(NavigationEventArgs) 方法。当用户导航离开页面时,将会调用此方法。在此方法中,包含 UI 控件值的 ViewModel 对象将保存到页面的 State 字典中。当逻辑删除应用时,将会保留“状态”字典,以便在重新激活应用时,可以使用该字典还原状态。如果导航为向后导航,当导航完成时将会释放页面,则没有必要保存状态。 将以下方法定义复制到 MainPage 类定义中。

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
    {
      // If this is a back navigation, the page will be discarded, so there
      // is no need to save state.
      if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
      {
        // Save the ViewModel variable in the page's State dictionary.
        State["ViewModel"] = _viewModel;
      }
    }
    
    
  12. 最后,重写 OnNavigatedTo(NavigationEventArgs) 方法。当用户导航到此页面时,将会调用此方法。这包括当首次启动应用并首次显示页面时、当应用被逻辑删除并且用户返回该应用时,以及当用户在单个实例的页面中导航时。

    首次,查看 _isNewPageInstance 是否为 true。如果不是,则您可以获知页面实例已经存储于内存中。这意味着 UI 状态保持了原样,并且无需还原控件值。如果它是新页面实例,请查看包含 UI 值的 ViewModel 对象是否存储在页面的“状态”字典中。如果是,请将保存的对象分配给 _viewModel 成员变量;否则,不存在已保存的状态,需要创建一个新的 ViewModel 实例。将页面的 DataContext 设置为 ViewModel 对象。这将更新所有的 UI 控件以显示保存在对象中的值。 最后,该方法将 _isNewPageInstance 变量设置为 false,以便在用户导航回到此页面,而此时该页面仍位于内存中的情况下,UI 将不会在 OnNavigatedTo 中还原。

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
      // If _isNewPageInstance is true, the page constuctor has been called, so
      // state may need to be restored.
      if (_isNewPageInstance)
      {
        if (_viewModel == null)
        {
          if (State.Count > 0)
          {
            _viewModel = (ViewModel)State["ViewModel"];
          }
          else
          {
            _viewModel = new ViewModel();
          }
        }
        DataContext = _viewModel;
      }
      // Set _isNewPageInstance to false. If the user navigates back to this page
      // and it has remained in memory, this value will continue to be false.
      _isNewPageInstance = false;
    }
    
    

在 Windows Phone OS 7.1 中,只要有足够的内存可供前台应用顺畅运行,应用就会在用户导航离开时置于休眠状态。当应用休眠后还原时,UI 状态会自动保留。若要验证页面状态在逻辑删除后是否正确还原,您需要启用调试器中的自动逻辑删除功能。

通过从“项目”菜单中选择“[应用程序名称] 属性…”,或者通过右键单击“解决方案资源管理器”中的项目,然后选择“属性”,打开“项目属性”。在“调试”标签中,选中标有“在调试期间取消激活时逻辑删除”的复选框。选中此复选框后,可以开始调试应用,点按“开始”按键将立即逻辑删除应用,然后按“返回”按键返回应用,并验证页面状态是否正确保存和还原。

说明注意:

对于 XNA Framework 应用,“在调试期间取消激活时逻辑删除”复选框位于“项目属性”对话框的“XNA Game Studio”标签中。

显示:
© 2014 Microsoft