Windows8 Metro开发 (04) : 保存/读取本地应用程序设置
生活随笔
收集整理的這篇文章主要介紹了
Windows8 Metro开发 (04) : 保存/读取本地应用程序设置
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
有些時候我們需要保存應用程序的設置,如用戶的系統設定。在Android中,我們可以使用sharepreference。在Metro中我們該怎么做呢?
保存/讀取基本類型數據
Metro程序會把要保存的數據寫入ApplicationData.Current.LocalSettings字典中,并保存在本地。程序在開始運行的時候會從本地初始化該字典。加載之前保存的數據。這樣我們就可以方便的保存/讀取基本類型數據了。 我將其封裝成了一個工具類。 [csharp]?view plaincopyprint? using?System;?? using?System.Collections.Generic;?? using?System.Linq;?? using?System.Text;?? using?System.Threading.Tasks;?? using?Windows.Storage;?? ?? namespace?Win8_Study.Pages?? {?? ????class?LocalDataUtil?? ????{?? ????????#region?保存/讀取基本類型數據?? ????????public?static?void?SaveData(string?key,?object?value)?? ????????{?? ????????????ApplicationData.Current.LocalSettings.Values[key]?=?value;?? ????????}?? ?? ????????public?static?object?GetData(string?key)?? ????????{?? ????????????return?ApplicationData.Current.LocalSettings.Values[key];?? ????????}?? ?? ?? ????????public?static?void?RemoveData(string?key)?? ????????{?? ????????????ApplicationData.Current.LocalSettings.Values.Remove(key);?? ????????}?? ????????#endregion?? ????}?? }??
下面我們來看一個示例:
默認顯示的字體大小為24,我們將其字體改為28后返回到主頁面,然后重新進入該頁面。你會發現字體的大小變為28了。 重新啟動程序進入該頁面,你會發現字體的大小仍然為28。 下拉列表的選中項與字體大小是時刻對應的.
實現方法如下: 1.每次進入該頁面的時候,首先獲取之前保存的字體大小 a.沒有獲取到 將字體大小設為默認值 b.獲取到 將字體大小設為獲取的值 2.用戶改變字體大小時,保存改變后的值 [csharp]?view plaincopyprint? ????public?sealed?partial?class?LocalDataPage?:?Win8_Study.Common.LayoutAwarePage?? ????{?? ????????private?readonly?string?TEXT_VALUE?=?"國米_百度百科\n"?+?? ????????????"國際米蘭足球俱樂部(Football?Club?Internazionale?Milano,簡稱?Inter?或?Internazionale)"?+?? ????????????"是一家位于意大利北部倫巴第區米蘭市的足球俱樂部。";?? ????????private?readonly?double?TEXT_FONT_SIZE?=?24;?? ????????private?readonly?string?TEXT_FONT_SIZE_KEY?=?"LocalDataPage-TEXT_FONT_SIZE_KEY";?? ?? ????????public?LocalDataPage()?? ????????{?? ????????????this.InitializeComponent();?? ????????}?? ?? ????????protected?override?void?LoadState(Object?navigationParameter,?Dictionary<String,?Object>?pageState)?? ????????{?? ????????????Init();?? ????????}?? ?? ?? ????????private?void?Init()?? ????????{?? ????????????//首先讀取之前保存的設置,如果為空設置成默認狀態?? ????????????InitFontSize();?? ????????????leftTextBlock.Text?=?TEXT_VALUE;?? ????????}?? ?? ????????protected?override?void?SaveState(Dictionary<String,?Object>?pageState)?? ????????{?? ????????}?? ?? ????????#region?保存程序設置?? ????????private?void?OnLeftComboBoxSelectionChanged(object?sender,?SelectionChangedEventArgs?e)?? ????????{?? ????????????var?comboBox?=?sender?as?ComboBox;?? ????????????var?item?=?comboBox.SelectedItem?as?ComboBoxItem;?? ????????????SetTextFontSize(Convert.ToDouble(item.Content));?? ????????}?? ?? ????????private?void?SetTextFontSize(double?size)?? ????????{?? ????????????leftTextBlock.FontSize?=?size;?? ????????????LocalDataUtil.SaveData(TEXT_FONT_SIZE_KEY,?size);?? ????????}?? ?? ????????private?void?InitFontSize()?? ????????{?? ????????????var?obj?=?LocalDataUtil.GetData(TEXT_FONT_SIZE_KEY);?? ????????????double?size?=?TEXT_FONT_SIZE;?? ????????????if?(obj?!=?null)?? ????????????{?? ????????????????size?=?Convert.ToDouble(obj);?? ????????????}?????? ????????????foreach?(var?element?in?leftFontSizeComboBox.Items)?? ????????????{?? ????????????????var?item?=?element?as?ComboBoxItem;?? ????????????????if?(item.Content.ToString().Equals(size.ToString()))?? ????????????????{?? ????????????????????leftFontSizeComboBox.SelectedItem?=?item;?? ????????????????????break;?? ????????????????}?? ????????????}?????????????? ????????}?? ????????#endregion?? ????????...?? ????}?? 或許你會嘗試著用這種方法去非基本類型的數據(比如Page,Color什么的)。嘿嘿,掛了吧。
那么我們該怎樣去保存非基本類型的數據呢?比如一個包含學生信息的集合?
保存/讀取非基本類型的數據--序列化/反序列化 保存程序的實時數據是十分必要的。比如你從網絡上獲取了一些娛樂新聞并顯示給用戶,你需要將這些數據保存下來,以便程序下次運行的時候使用。 下次運行程序的時候,這些數據就會變成本地的了,加載速度會非常快,因為你不需要再去從網絡獲取數據。 如果你不這樣做的話,用戶可能會在網絡非常擁塞的情況下看到一個非常"干凈"的屏幕。這個時候你的應用也許會被(應該是必須)。。。
舉一個"稍微"復雜點的例子 現在有Student,Coder兩個類,它們都繼承了父類People。 [csharp]?view plaincopyprint? using?System;?? using?System.Collections.Generic;?? using?System.Linq;?? using?System.Runtime.Serialization;?? using?System.Text;?? using?System.Threading.Tasks;?? ?? namespace?Win8_Study.Pages?? {?? ????[DataContract]?? ????public?abstract?class?People?? ????{?? ????????[DataMember]?? ????????public?string?Name?{?get;?set;?}?? ????????[DataMember]?? ????????public?int?Age?{?get;?set;?}?? ?? ????????public?People(string?name,int?age)?? ????????{?? ????????????this.Name?=?name;?? ????????????this.Age?=?age;?? ????????}?? ????}?? ?? ????[DataContract]?? ????public?class?Student?:?People?? ????{?? ????????[DataMember]?? ????????public?int?Score?{?get;?set;?}?? ?? ????????public?Student(string?name,?int?age,?int?score)?? ????????????:?base(name,?age)?? ????????{?? ????????????this.Score?=?score;?? ????????}?? ????}?? ?? ????[DataContract]?? ????public?class?Coder?:?People?? ????{?? ????????[DataMember]?? ????????public?int?WorkYears?{?get;?set;?}?? ?? ????????public?Coder(string?name,?int?age,?int?workYears)?? ????????????:?base(name,?age)?? ????????{?? ????????????this.WorkYears?=?workYears;?? ????????}?? ????}?? }?? 我們需要在ListView上隨機顯示一些學生和程序員的信息,并保存下來。然后清空ListView,讀取保存的數據,看結果與之前的是否相同。
創建學生和程序員信息的方法很簡單,在這里創建5-10條信息,每條信息的內容隨機顯示: [csharp]?view plaincopyprint? private?List<People>?GetPeopleDatas()?? ????????{?? ????????????List<People>?peoples?=?new?List<People>();?? ????????????Random?ran?=?new?Random(DateTime.Now.Millisecond);?? ????????????int?count?=?ran.Next(5)?+?5;//5?-?10?? ????????????for?(int?i?=?0;?i?<?count;?++i)?? ????????????{?? ????????????????int?type?=?ran.Next(2);?? ????????????????if?(type?==?0)?? ????????????????{?? ????????????????????peoples.Add(new?Student("學生"?+?(i?+?1),?ran.Next(12)?+?6,?60?+?ran.Next(41)));?? ????????????????}?? ????????????????else?? ????????????????{?? ????????????????????peoples.Add(new?Coder("程序員"?+?(i?+?1),?ran.Next(10)?+?22,?ran.Next(5)));?? ????????????????}?? ????????????}?? ????????????return?peoples;?? ????????}?? 根據類別創建不同ListView項
[csharp]?view plaincopyprint? private?void?OnRightRandomAddDataButtonClicked(object?sender,?RoutedEventArgs?e)?? ????????{?? ????????????_peoples?=?GetPeopleDatas();?? ????????????SetListViewData(_peoples);?? ????????}?? [csharp]?view plaincopyprint? private?void?SetListViewData(List<People>?peoples)?? {?? ????itemListView.Items.Clear();?? ????foreach?(People?p?in?peoples)?? ????{?? ????????ListViewItem?item?=?new?ListViewItem();?? ????????item.FontSize?=?20;?? ????????if?(p?is?Student)?? ????????{?? ????????????Student?s?=?p?as?Student;?? ????????????item.Content?=?string.Format("{0}?年齡:{1}?成績:?{2}",?s.Name,?s.Age,?s.Score);?? ????????}?? ????????else?? ????????{?? ????????????Coder?c?=?p?as?Coder;?? ????????????item.Content?=?string.Format("{0}?年齡:{1}?工作時間:?{2}年",?c.Name,?c.Age,?c.WorkYears);?? ????????}?? ????????itemListView.Items.Add(item);?? ????}?? }??
保存數據 [csharp]?view plaincopyprint? ????????private?async?void?OnRightSaveDataButtonClicked(object?sender,?RoutedEventArgs?e)?? ????????{?? ????????????await?SerializerUtil.XMLSerialize(_peoples,typeof(List<People>));?? ????????????await?PopupUtil.ShowMessageDialog(string.Format("保存數據成功!?item數量{0}",_peoples.Count),?"提示");?? ????????}?? 注意到People,Student,Coder中的序列化標志的嗎?不添加的話是無法序列化的。
其中?SerializerUtil.XMLSerialize是我封裝的序列化代碼的方法,其實現方式如下:
[csharp]?view plaincopyprint? public?static?async?Task?XMLSerialize(object?instance,?Type?type)?? {?? ????//取得當前程序存放數據的目錄?? ????StorageFolder?folder?=?Windows.Storage.ApplicationData.Current.LocalFolder;?? ????//定義文件名?? ????string?fileName?=?"LocalDataPage-list_data.xml";?? ????//創建文件,如果文件存在就覆蓋?? ????StorageFile?newFile?=?await?folder.CreateFileAsync(fileName,?CreationCollisionOption.ReplaceExisting)?? ????//將內容序列化至文件?? ????Stream?newFileStream?=?await?newFile.OpenStreamForWriteAsync();?? ????DataContractSerializer?ser?=?new?DataContractSerializer(type,?GetTypes());?? ????ser.WriteObject(newFileStream,?instance);?? ????newFileStream.Dispose();?? }?? 注意GetTypes()方法,在序列化的時候需要指定序列化對象的類型集合。在這里需要序列化的數據類型有3個:People,Student,Coder。所以我們應該這樣設定:
[csharp]?view plaincopyprint? private?static?ObservableCollection<Type>?GetTypes()?? ????????{?? ????????????//添加要序列化的類型?? ????????????if?(_Types?==?null)?? ????????????{?? ????????????????_Types?=?new?ObservableCollection<Type>();?? ????????????????_Types.Add(typeof(People));?? ????????????????_Types.Add(typeof(Student));?? ????????????????_Types.Add(typeof(Coder));?? ????????????}?? ????????????return?_Types;?? ????????}?? 其中_Types是全局對象ObservableCollection<Type>。
至此,數據就保存好了。
讀取數據 讀取數據也就是進行反序列化,我們可以得到之前保存的對象集合,其數據類型是List<People>,然后我們將該對象集合交給ListView顯示即可。 [csharp]?view plaincopyprint? private?async?void?OnRightLoadDataButtonClicked(object?sender,?RoutedEventArgs?e)?? ????????{?? ????????????try?? ????????????{?? ????????????????var?obj?=?await?SerializerUtil.XMLDeserialize(typeof(List<People>));?? ????????????????_peoples?=?obj?as?List<People>;?? ????????????????SetListViewData(_peoples);?? ????????????????await?PopupUtil.ShowMessageDialog(string.Format("讀取數據成功!?item數量{0}",?_peoples.Count),?? ????????????????????"提示");?? ????????????????return;?? ????????????}?? ????????????catch?(FileNotFoundException)?? ????????????{?? ?????????????????? ????????????}?? ????????????await?PopupUtil.ShowMessageDialog("你還沒有保存數據。",?"提示");?? ????????}?? 反序列化
[csharp]?view plaincopyprint? public?static?async?Task<object>?XMLDeserialize(Type?type)?? ???????{?? ???????????StorageFolder?folder?=?Windows.Storage.ApplicationData.Current.LocalFolder;?? ???????????string?fileName?=?"LocalDataPage-list_data.xml";?? ???????????StorageFile?newFile?=?await?folder.GetFileAsync(fileName);?? ???????????Stream?newFileStream?=?await?newFile.OpenStreamForReadAsync();?? ???????????//進行反序列化?? ???????????DataContractSerializer?ser?=?new?DataContractSerializer(type,?GetTypes());?? ???????????object?instance?=?ser.ReadObject(newFileStream);?? ???????????newFileStream.Dispose();?? ???????????return?instance;?? ???????}?? 可以看到讀取的數據與之前保存的相同.我們的目的達到了。
程序運行的效果如下: 1.隨機顯示學生和程序員信息: 2.保存數據 保存文件的內容 [html]?view plaincopyprint? <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.清除數據并讀取之前保存的數據
顯示效果同第一張圖.
保存/讀取基本類型數據
Metro程序會把要保存的數據寫入ApplicationData.Current.LocalSettings字典中,并保存在本地。程序在開始運行的時候會從本地初始化該字典。加載之前保存的數據。這樣我們就可以方便的保存/讀取基本類型數據了。 我將其封裝成了一個工具類。 [csharp]?view plaincopyprint?
下面我們來看一個示例:
默認顯示的字體大小為24,我們將其字體改為28后返回到主頁面,然后重新進入該頁面。你會發現字體的大小變為28了。 重新啟動程序進入該頁面,你會發現字體的大小仍然為28。 下拉列表的選中項與字體大小是時刻對應的.
實現方法如下: 1.每次進入該頁面的時候,首先獲取之前保存的字體大小 a.沒有獲取到 將字體大小設為默認值 b.獲取到 將字體大小設為獲取的值 2.用戶改變字體大小時,保存改變后的值 [csharp]?view plaincopyprint?
保存/讀取非基本類型的數據--序列化/反序列化 保存程序的實時數據是十分必要的。比如你從網絡上獲取了一些娛樂新聞并顯示給用戶,你需要將這些數據保存下來,以便程序下次運行的時候使用。 下次運行程序的時候,這些數據就會變成本地的了,加載速度會非常快,因為你不需要再去從網絡獲取數據。 如果你不這樣做的話,用戶可能會在網絡非常擁塞的情況下看到一個非常"干凈"的屏幕。這個時候你的應用也許會被(應該是必須)。。。
舉一個"稍微"復雜點的例子 現在有Student,Coder兩個類,它們都繼承了父類People。 [csharp]?view plaincopyprint?
創建學生和程序員信息的方法很簡單,在這里創建5-10條信息,每條信息的內容隨機顯示: [csharp]?view plaincopyprint?
保存數據 [csharp]?view plaincopyprint?
[csharp]?view plaincopyprint?
讀取數據 讀取數據也就是進行反序列化,我們可以得到之前保存的對象集合,其數據類型是List<People>,然后我們將該對象集合交給ListView顯示即可。 [csharp]?view plaincopyprint?
程序運行的效果如下: 1.隨機顯示學生和程序員信息: 2.保存數據 保存文件的內容 [html]?view plaincopyprint?
總結
以上是生活随笔為你收集整理的Windows8 Metro开发 (04) : 保存/读取本地应用程序设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows8 Metro开发 (02
- 下一篇: Win 10 UWP开发系列:设置App