有些时候我们需要保存应用程序的设置,如用户的系统设定。在Android中,我们可以使用sharepreference。在Metro中我们该怎么做呢?
保存/读取基本类型数据
Metro程序会把要保存的数据写入ApplicationData.Current.LocalSettings字典中,并保存在本地。程序在开始运行的时候会从本地初始化该字典。加载之前保存的数据。这样我们就可以方便的保存/读取基本类型数据了。
我将其封装成了一个工具类。
[csharp] view plaincopyprint?
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Windows.Storage;
  7. namespace Win8_Study.Pages
  8. {
  9. class LocalDataUtil
  10. {
  11. #region 保存/读取基本类型数据
  12. public static void SaveData(string key, object value)
  13. {
  14. ApplicationData.Current.LocalSettings.Values[key] = value;
  15. }
  16. public static object GetData(string key)
  17. {
  18. return ApplicationData.Current.LocalSettings.Values[key];
  19. }
  20. public static void RemoveData(string key)
  21. {
  22. ApplicationData.Current.LocalSettings.Values.Remove(key);
  23. }
  24. #endregion
  25. }
  26. }
下面我们来看一个示例:
默认显示的字体大小为24,我们将其字体改为28后返回到主页面,然后重新进入该页面。你会发现字体的大小变为28了。
重新启动程序进入该页面,你会发现字体的大小仍然为28。
下拉列表的选中项与字体大小是时刻对应的.
实现方法如下
1.每次进入该页面的时候,首先获取之前保存的字体大小
a.没有获取到
将字体大小设为默认值
b.获取到
将字体大小设为获取的值
2.用户改变字体大小时,保存改变后的值

[csharp] view plaincopyprint?
  1. public sealed partial class LocalDataPage : Win8_Study.Common.LayoutAwarePage
  2. {
  3. private readonly string TEXT_VALUE = "国米_百度百科\n" +
  4. "国际米兰足球俱乐部(Football Club Internazionale Milano,简称 Inter 或 Internazionale)" +
  5. "是一家位于意大利北部伦巴第区米兰市的足球俱乐部。";
  6. private readonly double TEXT_FONT_SIZE = 24;
  7. private readonly string TEXT_FONT_SIZE_KEY = "LocalDataPage-TEXT_FONT_SIZE_KEY";
  8. public LocalDataPage()
  9. {
  10. this.InitializeComponent();
  11. }
  12. protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
  13. {
  14. Init();
  15. }
  16. private void Init()
  17. {
  18. //首先读取之前保存的设置,如果为空设置成默认状态
  19. InitFontSize();
  20. leftTextBlock.Text = TEXT_VALUE;
  21. }
  22. protected override void SaveState(Dictionary<String, Object> pageState)
  23. {
  24. }
  25. #region 保存程序设置
  26. private void OnLeftComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
  27. {
  28. var comboBox = sender as ComboBox;
  29. var item = comboBox.SelectedItem as ComboBoxItem;
  30. SetTextFontSize(Convert.ToDouble(item.Content));
  31. }
  32. private void SetTextFontSize(double size)
  33. {
  34. leftTextBlock.FontSize = size;
  35. LocalDataUtil.SaveData(TEXT_FONT_SIZE_KEY, size);
  36. }
  37. private void InitFontSize()
  38. {
  39. var obj = LocalDataUtil.GetData(TEXT_FONT_SIZE_KEY);
  40. double size = TEXT_FONT_SIZE;
  41. if (obj != null)
  42. {
  43. size = Convert.ToDouble(obj);
  44. }
  45. foreach (var element in leftFontSizeComboBox.Items)
  46. {
  47. var item = element as ComboBoxItem;
  48. if (item.Content.ToString().Equals(size.ToString()))
  49. {
  50. leftFontSizeComboBox.SelectedItem = item;
  51. break;
  52. }
  53. }
  54. }
  55. #endregion
  56. ...
  57. }

或许你会尝试着用这种方法去非基本类型的数据(比如Page,Color什么的)。嘿嘿,挂了吧。

那么我们该怎样去保存非基本类型的数据呢?比如一个包含学生信息的集合?
保存/读取非基本类型的数据--序列化/反序列化
保存程序的实时数据是十分必要的。比如你从网络上获取了一些娱乐新闻并显示给用户,你需要将这些数据保存下来,以便程序下次运行的时候使用。
下次运行程序的时候,这些数据就会变成本地的了,加载速度会非常快,因为你不需要再去从网络获取数据。
如果你不这样做的话,用户可能会在网络非常拥塞的情况下看到一个非常"干净"的屏幕。这个时候你的应用也许会被(应该是必须)。。。
举一个"稍微"复杂点的例子
现在有Student,Coder两个类,它们都继承了父类People。
[csharp] view plaincopyprint?
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace Win8_Study.Pages
  8. {
  9. [DataContract]
  10. public abstract class People
  11. {
  12. [DataMember]
  13. public string Name { get; set; }
  14. [DataMember]
  15. public int Age { get; set; }
  16. public People(string name,int age)
  17. {
  18. this.Name = name;
  19. this.Age = age;
  20. }
  21. }
  22. [DataContract]
  23. public class Student : People
  24. {
  25. [DataMember]
  26. public int Score { get; set; }
  27. public Student(string name, int age, int score)
  28. : base(name, age)
  29. {
  30. this.Score = score;
  31. }
  32. }
  33. [DataContract]
  34. public class Coder : People
  35. {
  36. [DataMember]
  37. public int WorkYears { get; set; }
  38. public Coder(string name, int age, int workYears)
  39. : base(name, age)
  40. {
  41. this.WorkYears = workYears;
  42. }
  43. }
  44. }

我们需要在ListView上随机显示一些学生和程序员的信息,并保存下来。然后清空ListView,读取保存的数据,看结果与之前的是否相同。

创建学生和程序员信息的方法很简单,在这里创建5-10条信息,每条信息的内容随机显示:
[csharp] view plaincopyprint?
  1. private List<People> GetPeopleDatas()
  2. {
  3. List<People> peoples = new List<People>();
  4. Random ran = new Random(DateTime.Now.Millisecond);
  5. int count = ran.Next(5) + 5;//5 - 10
  6. for (int i = 0; i < count; ++i)
  7. {
  8. int type = ran.Next(2);
  9. if (type == 0)
  10. {
  11. peoples.Add(new Student("学生" + (i + 1), ran.Next(12) + 6, 60 + ran.Next(41)));
  12. }
  13. else
  14. {
  15. peoples.Add(new Coder("程序员" + (i + 1), ran.Next(10) + 22, ran.Next(5)));
  16. }
  17. }
  18. return peoples;
  19. }

根据类别创建不同ListView项

[csharp] view plaincopyprint?
  1. private void OnRightRandomAddDataButtonClicked(object sender, RoutedEventArgs e)
  2. {
  3. _peoples = GetPeopleDatas();
  4. SetListViewData(_peoples);
  5. }
[csharp] view plaincopyprint?
  1. private void SetListViewData(List<People> peoples)
  2. {
  3. itemListView.Items.Clear();
  4. foreach (People p in peoples)
  5. {
  6. ListViewItem item = new ListViewItem();
  7. item.FontSize = 20;
  8. if (p is Student)
  9. {
  10. Student s = p as Student;
  11. item.Content = string.Format("{0} 年龄:{1} 成绩: {2}", s.Name, s.Age, s.Score);
  12. }
  13. else
  14. {
  15. Coder c = p as Coder;
  16. item.Content = string.Format("{0} 年龄:{1} 工作时间: {2}年", c.Name, c.Age, c.WorkYears);
  17. }
  18. itemListView.Items.Add(item);
  19. }
  20. }

保存数据

[csharp] view plaincopyprint?
  1. private async void OnRightSaveDataButtonClicked(object sender, RoutedEventArgs e)
  2. {
  3. await SerializerUtil.XMLSerialize(_peoples,typeof(List<People>));
  4. await PopupUtil.ShowMessageDialog(string.Format("保存数据成功! item数量{0}",_peoples.Count), "提示");
  5. }

注意到People,Student,Coder中的序列化标志的吗?不添加的话是无法序列化的。

其中 SerializerUtil.XMLSerialize是我封装的序列化代码的方法,其实现方式如下:
[csharp] view plaincopyprint?
  1. public static async Task XMLSerialize(object instance, Type type)
  2. {
  3. //取得当前程序存放数据的目录
  4. StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
  5. //定义文件名
  6. string fileName = "LocalDataPage-list_data.xml";
  7. //创建文件,如果文件存在就覆盖
  8. StorageFile newFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting)
  9. //将内容序列化至文件
  10. Stream newFileStream = await newFile.OpenStreamForWriteAsync();
  11. DataContractSerializer ser = new DataContractSerializer(type, GetTypes());
  12. ser.WriteObject(newFileStream, instance);
  13. newFileStream.Dispose();
  14. }

注意GetTypes()方法,在序列化的时候需要指定序列化对象的类型集合。在这里需要序列化的数据类型有3个:People,Student,Coder。所以我们应该这样设定:

[csharp] view plaincopyprint?
  1. private static ObservableCollection<Type> GetTypes()
  2. {
  3. //添加要序列化的类型
  4. if (_Types == null)
  5. {
  6. _Types = new ObservableCollection<Type>();
  7. _Types.Add(typeof(People));
  8. _Types.Add(typeof(Student));
  9. _Types.Add(typeof(Coder));
  10. }
  11. return _Types;
  12. }

其中_Types是全局对象ObservableCollection<Type>。

至此,数据就保存好了。
读取数据
读取数据也就是进行反序列化,我们可以得到之前保存的对象集合,其数据类型是List<People>,然后我们将该对象集合交给ListView显示即可。
[csharp] view plaincopyprint?
  1. private async void OnRightLoadDataButtonClicked(object sender, RoutedEventArgs e)
  2. {
  3. try
  4. {
  5. var obj = await SerializerUtil.XMLDeserialize(typeof(List<People>));
  6. _peoples = obj as List<People>;
  7. SetListViewData(_peoples);
  8. await PopupUtil.ShowMessageDialog(string.Format("读取数据成功! item数量{0}", _peoples.Count),
  9. "提示");
  10. return;
  11. }
  12. catch (FileNotFoundException)
  13. {
  14. }
  15. await PopupUtil.ShowMessageDialog("你还没有保存数据。", "提示");
  16. }

反序列化

[csharp] view plaincopyprint?
  1. public static async Task<object> XMLDeserialize(Type type)
  2. {
  3. StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
  4. string fileName = "LocalDataPage-list_data.xml";
  5. StorageFile newFile = await folder.GetFileAsync(fileName);
  6. Stream newFileStream = await newFile.OpenStreamForReadAsync();
  7. //进行反序列化
  8. DataContractSerializer ser = new DataContractSerializer(type, GetTypes());
  9. object instance = ser.ReadObject(newFileStream);
  10. newFileStream.Dispose();
  11. return instance;
  12. }

可以看到读取的数据与之前保存的相同.我们的目的达到了。

程序运行的效果如下:
1.随机显示学生和程序员信息:

2.保存数据
保存文件的内容
[html] view plaincopyprint?
  1. <ArrayOfPeople xmlns="http://schemas.datacontract.org/2004/07/Win8_Study.Pages" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><People i:type="Student"><Age>14</Age><Name>学生1</Name><Score>66</Score></People><People i:type="Coder"><Age>24</Age><Name>程序员2</Name><WorkYears>4</WorkYears></People><People i:type="Student"><Age>7</Age><Name>学生3</Name><Score>86</Score></People><People i:type="Coder"><Age>23</Age><Name>程序员4</Name><WorkYears>1</WorkYears></People><People i:type="Coder"><Age>25</Age><Name>程序员5</Name><WorkYears>2</WorkYears></People></ArrayOfPeople>
3.清除数据并读取之前保存的数据
显示效果同第一张图.

Windows8 Metro开发 (04) : 保存/读取本地应用程序设置相关推荐

  1. android怎么写本地图片,Android 开发图片保存在本地

    /** * 图片存储到本地 方法2 * * @param bitmap */ public static void compressImagetwo(Bitmap bitmap) { try { St ...

  2. Windows8 Metro开发 (02) : AppBar控件之TopAppBar

    Appbar分为2种: 显示在页面顶部的TopAppBar 显示在页面底部的BottomAppBar TopAppBar一般用于页面导航,BottomAppBar则用来处理一些用户事件. 本文仅介绍T ...

  3. Windows8 Metro开发 (03) : AppBar控件之BottomAppBar

    BottomAppBar 在介绍BottomAppBar之前还是先上张图. 这次我们关注底部的AppBar. 上图的AppBar分为左右2个部分. 左侧是引用系统自带的AppBar按钮,右侧是自定义的 ...

  4. Android开发 拍照+读取相册+保存到本地

    Android Studio 新建项目,Minimum SDK选择API 28: android 9.0(Pie),在华为Mate20 Pro 测试通过. AndroidManifest.xml中添加 ...

  5. qss qmenu 设置icon位置大小_实战PyQt5: 125-使用配置文件来保存和恢复应用的设置...

    在通常情况下,用户使用一个软件的时候,期望保存一些数据状态,比如窗口的大小和位置,主题,选项,最近操作过的文件等等信息,在下一次启动软件的时候就自动加载这些信息,让软件恢复到上一次退出时的状态.在Wi ...

  6. 使用Jlink读取单片机内部程序

    Jlink工具作为常用的调试工具,其亦可以单独下载文件到MCU,需要借助JFLASH工具,下载地址如下 https://www.segger.com/downloads/jlink/ 直接下载jlin ...

  7. (Metro学习三)图片uri保存到本地图片库

    已知网络上图片的uri地址,如何将网络图片保存到本地呢?代码如下: 保存图片到本地 private async Task SaveImageFromUrl(string uri, string fil ...

  8. Java开发Twitter爬虫抓取图片和视频并保存到本地

    零.目标 使用Java开发爬虫,爬取Twitter状态下评论中的图片和视频,并将其保存到本地. 一.调研爬虫框架 Twitter4J: https://github.com/Twitter4J/Twi ...

  9. 【UWP通用应用开发】文件选取器、获取文件属性、写入和读取、保存读取和删除应用数据

    读取文件和文件夹名 这一节开始我们将陆续看到UWP通用应用是如何获取到文件及文件夹的属性等信息,以及如何写入和读取数据等,当然了最重要的还是如何保存读取和删除应用的数据. 在Windows上读取文件名 ...

最新文章

  1. 广发银行运维实践分享:Docker适配传统运维那些事
  2. python权限管理系统_PMS:支持多应用的统一权限管理系统,用flask+vue实现
  3. 技术解读|云上企业级存储——打开存储新维度,促进用户核心业务创新
  4. windows分辨率修改工具_Windows 字体优化,这几个办法能帮你解决
  5. C# 数值和字符串之间的相互转换
  6. rs232串口驱动_RS232与RS485在性能上有啥区别和联系?老电工总结分析,一目了然...
  7. redis.conf配置文件详解
  8. 【java】dubbo基础学习
  9. Python中fastapi构建的web项目配置环境变量
  10. C++《STL全集》
  11. FreeSWITCH 初步
  12. 划分数算法概述及习题
  13. 常用名词理解(APK,SDK,JDK,API,DLL)
  14. 设置自定义电脑屏幕分辨率
  15. 有谁知道win10appdata文件夹可以删除吗,删除的方法是什么
  16. 纯字母域名批量注册的详细步骤
  17. 增强现实(AR)、虚拟现实(VR)、混合现实(MR)之间有什么区别?
  18. qq邮箱邮件被拦截如何找回的方法
  19. 2014522420145238《信息安全系统设计基础》实验五
  20. docker项目切换(nginx)、重启shell 脚本

热门文章

  1. 【Groovy】Groovy 脚本调用 ( Groovy 类中调用 Groovy 脚本 | 参考 Script#evaluate 方法 | 创建 Binding 对象并设置 args 参数 )
  2. 【每日随笔】使用 you-get 获取网页中的视频资源 ( Python 环境安装 | you-get 工具使用 )
  3. 【Android FFMPEG 开发】Android 中使用 FFMPEG 对 MP3 文件进行混音操作
  4. 【Android 组件化】使用 Gradle 实现组件化 ( 组件模式与集成模式切换 )
  5. 【数据挖掘】决策树 分类 ( 抽取分类规则 | 过拟合 | 剪枝 | 先剪 | 后剪 | 连续数值离散化 | 最优化分点 | 增益率选择划分属性 )
  6. 【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]
  7. 4.15第8周 第一节
  8. 自定义 checkbox 新玩法 ?
  9. 多列布局——column-width
  10. 转:C#使用Log4Net记录日志