有些时候我们需要保存应用程序的设置,如用户的系统设定。在Android中,我们可以使用sharepreference。在Metro中我们该怎么做呢?
保存/读取基本类型数据
ApplicationData.Current.LocalSettings字典中,并保存在本地。程序在开始运行的时候会从本地初始化该字典。加载之前保存的数据。这样我们就可以方便的保存/读取基本类型数据了。
我将其封装成了一个工具类。
[csharp] view plain copy print ?
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.
8. namespace Win8_Study.Pages
9. {
10. class LocalDataUtil
11. {
12. #region 保存/读取基本类型数据
13. public static void SaveData(string key, object value)
14. {
15. ApplicationData.Current.LocalSettings.Values[key] = value;
16. }
17.
18. public static object GetData(string key)
19. {
20. return ApplicationData.Current.LocalSettings.Values[key];
21. }
22.
23.
24. public static void RemoveData(string key)
25. {
26. ApplicationData.Current.LocalSettings.Values.Remove(key);
27. }
28. #endregion
29. }
30. }
下面我们来看一个示例:
默认显示的字体大小为24,我们将其字体改为28后返回到主页面,然后重新进入该页面。你会发现字体的大小变为28了。
重新启动程序进入该页面,你会发现字体的大小仍然为28。
下拉列表的选中项与字体大小是时刻对应的.
实现方法如下:
1.每次进入该页面的时候,首先获取之前保存的字体大小
a.没有获取到
将字体大小设为默认值
b.获取到
将字体大小设为获取的值
2.用户改变字体大小时,保存改变后的值
[csharp] view plain copy print ?
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.
9. public LocalDataPage()
10. {
11. this.InitializeComponent();
12. }
13.
14. protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
15. {
16. Init();
17. }
18.
19.
20. private void Init()
21. {
22. //首先读取之前保存的设置,如果为空设置成默认状态
23. InitFontSize();
24. leftTextBlock.Text = TEXT_VALUE;
25. }
26.
27. protected override void SaveState(Dictionary<String, Object> pageState)
28. {
29. }
30.
31. #region 保存程序设置
32. private void OnLeftComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
33. {
34. as ComboBox;
35. as ComboBoxItem;
36. SetTextFontSize(Convert.ToDouble(item.Content));
37. }
38.
39. private void SetTextFontSize(double size)
40. {
41. leftTextBlock.FontSize = size;
42. LocalDataUtil.SaveData(TEXT_FONT_SIZE_KEY, size);
43. }
44.
45. private void InitFontSize()
46. {
47. var obj = LocalDataUtil.GetData(TEXT_FONT_SIZE_KEY);
48. double size = TEXT_FONT_SIZE;
49. if (obj != null)
50. {
51. size = Convert.ToDouble(obj);
52. }
53. foreach (var element in leftFontSizeComboBox.Items)
54. {
55. as ComboBoxItem;
56. if (item.Content.ToString().Equals(size.ToString()))
57. {
58. leftFontSizeComboBox.SelectedItem = item;
59. break;
60. }
61. }
62. }
63. #endregion
64. ...
65. }
那么我们该怎样去保存非基本类型的数据呢?比如一个包含学生信息的集合?
保存/读取非基本类型的数据--序列化/反序列化
保存程序的实时数据是十分必要的。比如你从网络上获取了一些娱乐新闻并显示给用户,你需要将这些数据保存下来,以便程序下次运行的时候使用。
下次运行程序的时候,这些数据就会变成本地的了,加载速度会非常快,因为你不需要再去从网络获取数据。
如果你不这样做的话,用户可能会在网络非常拥塞的情况下看到一个非常"干净"的屏幕。这个时候你的应用也许会被(应该是必须)。。。
举一个"稍微"复杂点的例子
现在有Student,Coder两个类,它们都继承了父类People。
[csharp] view plain copy print ?
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.
8. namespace Win8_Study.Pages
9. {
10. [DataContract]
11. public abstract class People
12. {
13. [DataMember]
14. public string Name { get; set; }
15. [DataMember]
16. public int Age { get; set; }
17.
18. public People(string name,int age)
19. {
20. this.Name = name;
21. this.Age = age;
22. }
23. }
24.
25. [DataContract]
26. public class Student : People
27. {
28. [DataMember]
29. public int Score { get; set; }
30.
31. public Student(string name, int age, int score)
32. base(name, age)
33. {
34. this.Score = score;
35. }
36. }
37.
38. [DataContract]
39. public class Coder : People
40. {
41. [DataMember]
42. public int WorkYears { get; set; }
43.
44. public Coder(string name, int age, int workYears)
45. base(name, age)
46. {
47. this.WorkYears = workYears;
48. }
49. }
50. }
我们需要在ListView上 随机显示一些学生和程序员的信息,并保存下来。然后清空ListView,读取保存的数据,看结果与之前的是否相同。
创建学生和程序员信息的方法很简单,在这里创建5-10条信息,每条信息的内容随机显示:
[csharp] view plain copy print ?
1. private List<People> GetPeopleDatas()
2. {
3. new List<People>();
4. 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. new Student("学生" + (i + 1), ran.Next(12) + 6, 60 + ran.Next(41)));
12. }
13. else
14. {
15. new Coder("程序员" + (i + 1), ran.Next(10) + 22, ran.Next(5)));
16. }
17. }
18. return peoples;
19. }
[csharp] view plain copy print ?
1. private void OnRightRandomAddDataButtonClicked(object sender, RoutedEventArgs e)
2. {
3. _peoples = GetPeopleDatas();
4. SetListViewData(_peoples);
5. }
[csharp] view plain copy print ?
1. private void SetListViewData(List<People> peoples)
2. {
3. itemListView.Items.Clear();
4. foreach (People p in peoples)
5. {
6. new ListViewItem();
7. item.FontSize = 20;
8. if (p is Student)
9. {
10. as Student;
11. string.Format("{0} 年龄:{1} 成绩: {2}", s.Name, s.Age, s.Score);
12. }
13. else
14. {
15. as Coder;
16. string.Format("{0} 年龄:{1} 工作时间: {2}年", c.Name, c.Age, c.WorkYears);
17. }
18. itemListView.Items.Add(item);
19. }
20. }
[csharp] view plain copy print ?
1. private async void OnRightSaveDataButtonClicked(object sender, RoutedEventArgs e)
2. {
3. typeof(List<People>));
4. string.Format("保存数据成功! item数量{0}",_peoples.Count), "提示");
5. }
其中 SerializerUtil.XMLSerialize是我封装的序列化代码的方法,其实现方式如下:
[csharp] view plain copy print ?
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. new DataContractSerializer(type, GetTypes());
12. ser.WriteObject(newFileStream, instance);
13. newFileStream.Dispose();
14. }
[csharp] view plain copy print ?
1. private static ObservableCollection<Type> GetTypes()
2. {
3. //添加要序列化的类型
4. if (_Types == null)
5. {
6. new ObservableCollection<Type>();
7. typeof(People));
8. typeof(Student));
9. typeof(Coder));
10. }
11. return _Types;
12. }
至此,数据就保存好了。
读取数据
读取数据也就是进行反序列化,我们可以得到之前保存的对象集合,其数据类型是List<People>,然后我们将该对象集合交给ListView显示即可。
[csharp] view plain copy print ?
1. private async void OnRightLoadDataButtonClicked(object sender, RoutedEventArgs e)
2. {
3. try
4. {
5. typeof(List<People>));
6. as List<People>;
7. SetListViewData(_peoples);
8. string.Format("读取数据成功! item数量{0}", _peoples.Count),
9. "提示");
10. return;
11. }
12. catch (FileNotFoundException)
13. {
14.
15. }
16. "你还没有保存数据。", "提示");
17. }
反序列化
[csharp] view plain copy print ?
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. new DataContractSerializer(type, GetTypes());
9. object instance = ser.ReadObject(newFileStream);
10. newFileStream.Dispose();
11. return instance;
12. }
程序运行的效果如下:
1.随机显示学生和程序员信息:
2.保存数据
保存文件的内容
[html] view plain copy print ?
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.清除数据并读取之前保存的数据
显示效果同第一张图.