功能简介
MainPage里面有一个Image控件和文本框控件,可以更改图片和在文本框中输入内容,Debug模式下选择生命周期事件中的挂起并关闭,重新打开之后还原之前图片的内容和文本框的内容
实现效果
- 启动
- 更改内容
- 挂起并关闭后再启动
实现过程
修改App.xaml.cs文件
- 在类App中添加一个变量,用于判断是否处于挂起状态
//App.cs
public bool isSuspend = false;
- 修改OnSuspending函数
private void OnSuspending(object sender, SuspendingEventArgs e)
{
this.isSuspend = true;
var deferral = e.SuspendingOperation.GetDeferral();
//保存应用程序状态并停止任何后台活动
Frame frameState = Window.Current.Content as Frame;
ApplicationData.Current.LocalSettings.Values["Navigation"] = frameState.GetNavigationState();
deferral.Complete();
}
- 在OnLaunched函数中添加代码
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{//添加的代码
rootFrame.SetNavigationState((string)ApplicationData.Current.LocalSettings.Values["Navigation"]);
}
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
Window.Current.Activate();
}
}
在MainPage.xaml中添加控件
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Image Source="/Assets/RedHood.jpg"></Image>
<TextBox Text="This is the default content"></TextBox>
<Button Content="PickPicture" Click="ChangeImage"></Button>
</StackPanel>
</Grid>
在MainPage.xaml.cs中添加代码
namespace onSuspendSample
{
public sealed partial class MainPage : Page
{
//source和Content用于保存Image控件的Source和文本框的内容
private string source = "";
private string content = "";
//prefix为LocalFolder的使用前缀
private string prefix = "ms-appdata:///local/";
public MainPage()
{
this.InitializeComponent();
}
//改变图片的按钮点击事件
private async void ChangeImage(object sender, RoutedEventArgs e)
{
//挑选图片
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.FileTypeFilter.Add(".jpg");
StorageFile file = await openPicker.PickSingleFileAsync();
//保存图片到LocalFolder
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile fileCopy = await file.CopyAsync(localFolder, file.Name, NameCollisionOption.ReplaceExisting);
BitmapImage bitmap = new BitmapImage();
using (var stream = await fileCopy.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
bitmap.SetSource(stream);
}
//source保存图片路径,挂起后重新打开将使用这个值进行还原
source = prefix + file.Name;
//设置图片控件的Image属性
MyImage.Source = bitmap;
}
//进入MainPage时调用
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//判断是第一次打开还是挂起后打开
if (e.NavigationMode == NavigationMode.New)
{
ApplicationData.Current.LocalSettings.Values.Remove("MainPage");
}
else
{
if (ApplicationData.Current.LocalSettings.Values.ContainsKey("MainPage"))
{
//还原值
ApplicationDataCompositeValue composite = ApplicationData.Current.LocalSettings.Values["MainPage"] as ApplicationDataCompositeValue;
source = composite["source"].ToString();
content = composite["content"].ToString();
ApplicationData.Current.LocalSettings.Values.Remove("MainPage");
}
//更新控件
UpdateWidget();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
/*
* OnNavigatedFrom在离开MainPage是会被调用,有可能是跳转到其他的页面,也有可能是挂起
* suspending判断是否为挂起
*/
bool suspending = ((App)App.Current).isSuspend;
if (suspending)
{
//如果是,将source,content的值保存下来,下次再打开的时候还原
ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue();
composite["source"] = source;
composite["content"] = MyTextBox.Text;
ApplicationData.Current.LocalSettings.Values["MainPage"] = composite;
}
}
//更新控件
private async void UpdateWidget()
{
//根据路径获取图片
var uri = new System.Uri(source);
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
BitmapImage bitmap = new BitmapImage();
using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
bitmap.SetSource(stream);
}
MyImage.Source = bitmap;
MyTextBox.Text = content;
}
}
}
需要注意的地方:
- 代码中LocalFolder的内容涉及UWP的文件操作,可以参考另一篇博客:UWP—文件操作
- 更改Image的图片后要更新source的值
- OnNavigatedFrom函数在离开MainPage时调用,该函数中添加的代码是为了保存控件的属性值
- OnNavigatedTo函数在进入MainPage时调用,如果是在挂起后重新进入MainPage,该函数将使用OnNavigatedFrom中保存的值还原Source和content,然后再通过UpdateWidget函数更新控件的属性值
总结
整个挂起并还原的功能最重要的就是两个部分:
- App.cs中添加代码是程序状态可以保存
- 在MainPage的OnNavigatedFrom函数中保存想要保存的值,在OnNavigatedTo函数中提取之前保存的值
Tips
需要注意的是,目前UWP挂起后能保存的数据必须是能序列化的, 即C#的基本类型,因此在页面跳转的时候不能传递自定义的类对象(其实就算不使用挂起功能的话也不推荐在页面跳转中传递自定义的对象,最好只传递基本类型,如果真的要让两个页面共用一个自定义的类对象的话,可以使用单例模式啊V●ᴥ●V)
FYI
项目下载:onSuspendSample
项目下载之后记住把Debug模式从ARM换成X86或X64(根据你自己的机型选择),之前一开始学习的时候不知道这一点,从网上下载下来的项目都运行不了,纠结的一逼(╥╯^╰╥)