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

有些时候我们需要保存应用程序的设置,如用户的系统设定。在Android中,我们可以使用sharepreference。在Metro中我们该怎么做呢?

保存/读取基本类型数据
 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.             var comboBox = sender as ComboBox;  
  35.             var item = comboBox.SelectedItem 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.                 var item = element as ComboBoxItem;  
  56.                 if (item.Content.ToString().Equals(size.ToString()))  
  57.                 {  
  58.                     leftFontSizeComboBox.SelectedItem = item;  
  59.                     break;  
  60.                 }  
  61.             }              
  62.         }  
  63.         #endregion  
  64.         ...  
  65.     }  
或许你会尝试着用这种方法去非基本类型的数据(比如Page,Color什么的)。嘿嘿,挂了吧。
那么我们该怎样去保存非基本类型的数据呢?比如一个包含学生信息的集合?

保存/读取非基本类型的数据--序列化/反序列化
保存程序的实时数据是十分必要的。比如你从网络上获取了一些娱乐新闻并显示给用户,你需要将这些数据保存下来,以便程序下次运行的时候使用。
下次运行程序的时候,这些数据就会变成本地的了,加载速度会非常快,因为你不需要再去从网络获取数据。
如果你不这样做的话,用户可能会在网络非常拥塞的情况下看到一个非常"干净"的屏幕。这个时候你的应用也许会被(应该是必须)。。。

举一个"稍微"复杂点的例子
现在有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 { getset; }  
  15.         [DataMember]  
  16.         public int Age { getset; }  
  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 { getset; }  
  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 { getset; }  
  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.             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 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.         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 plain copy print ?
  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 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.     DataContractSerializer ser = new DataContractSerializer(type, GetTypes());  
  12.     ser.WriteObject(newFileStream, instance);  
  13.     newFileStream.Dispose();  
  14. }  
注意GetTypes()方法,在序列化的时候需要指定序列化对象的类型集合。在这里需要序列化的数据类型有3个:People,Student,Coder。所以我们应该这样设定:
[csharp]  view plain copy print ?
  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 plain copy print ?
  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.             }  
  16.             await PopupUtil.ShowMessageDialog("你还没有保存数据。""提示");  
  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.            DataContractSerializer ser = 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.清除数据并读取之前保存的数据
显示效果同第一张图.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值