在开发过程中,我们需要将某些数据保存下来,比如一些设置信息以及一些用户主动去保存的数据。待用户下次打开应用时候,再自动加载这些信息。下面将介绍windows8开发中如何存储数据。
一.本地数据存储
在wp中我们使用IsolatedStorageSettings进行本地数据存储,在win8中也提供类似的方法进行存储,我们使用ApplicationData.Current.LocalSettings。下面将通过实例进行描述:
在节目上添加姓名、年龄、性别三个控件,代码如下:
1 <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 2 <StackPanel Margin="40,40,0,0"> 3 <StackPanel Orientation="Horizontal" Height="80"> 4 <TextBlock Text="姓名:" Style="{StaticResource BasicTextStyle}" FontSize="20" VerticalAlignment="Center"/> 5 <TextBox x:Name="txtName" Text="" FontSize="24" Width="200" Height="40"/> 6 </StackPanel> 7 <StackPanel Orientation="Horizontal" Height="80"> 8 <TextBlock Text="年龄:" Style="{StaticResource BasicTextStyle}" FontSize="20" VerticalAlignment="Center"/> 9 <TextBox x:Name="txtAge" Text="" FontSize="24" Width="200" Height="40"/> 10 </StackPanel> 11 <StackPanel Orientation="Horizontal" Height="80"> 12 <TextBlock Text="性别:" Style="{StaticResource BasicTextStyle}" FontSize="20" VerticalAlignment="Center"/> 13 <ComboBox x:Name="cbxSex" Height="40" Width="200" SelectedIndex="1"> 14 <ComboBoxItem>男</ComboBoxItem> 15 <ComboBoxItem>女</ComboBoxItem> 16 </ComboBox> 17 </StackPanel> 18 <StackPanel Orientation="Horizontal"> 19 <Button Content="保存" Width="100" Height="40" FontSize="16" Click="btnSave_Click"></Button> 20 <Button Margin="20,0,0,0" Content="读取" Width="100" Height="40" FontSize="16" Click="btnRead_Click"></Button> 21 <Button Margin="20,0,0,0" Content="清空" Width="100" Height="40" FontSize="16" Click="btnClear_Click"></Button> 22 </StackPanel> 23 </StackPanel> 24 </Grid>
新建类AppDataHelper.cs,引用命名空间using Windows.Storage。我们将读取和保存封装成共通,方便调用。
保存数据:
1 /// <summary> 2 /// 保存数据 3 /// </summary> 4 /// <typeparam name="T">数据类型</typeparam> 5 /// <param name="key">键</param> 6 /// <param name="value">值</param> 7 public static void Save<T>(string key, T value) 8 { 9 ApplicationData.Current.LocalSettings.Values[key] = value; 10 }
读取数据:
1 /// <summary> 2 /// 读取数据 3 /// </summary> 4 /// <typeparam name="T">数据类型</typeparam> 5 /// <param name="key">键</param> 6 /// <returns>值</returns> 7 public static T Read<T>(string key) 8 { 9 if (ApplicationData.Current.LocalSettings.Values.ContainsKey(key)) 10 { 11 return (T)ApplicationData.Current.LocalSettings.Values[key]; 12 } 13 else 14 { 15 return default(T); 16 } 17 }
删除数据:
1 /// <summary> 2 /// 移除数据 3 /// </summary> 4 /// <param name="key">键</param> 5 /// <returns>成功true/失败false</returns> 6 public static bool Remove(string key) 7 { 8 return ApplicationData.Current.LocalSettings.Values.Remove(key); 9 }
我们只要在需要存储或者读取数据的地方进行调用,就可以了。
1 private void btnSave_Click(object sender, RoutedEventArgs e) 2 { 3 AppDataHelper.Save<string>("name", txtName.Text.Trim()); 4 AppDataHelper.Save<int>("age", int.Parse(txtAge.Text.Trim())); 5 AppDataHelper.Save<int>("sex", cbxSex.SelectedIndex); 6 } 7 private void btnRead_Click(object sender, RoutedEventArgs e) 8 { 9 txtName.Text = AppDataHelper.Read<string>("name"); 10 txtAge.Text = AppDataHelper.Read<int>("age").ToString(); 11 cbxSex.SelectedIndex = AppDataHelper.Read<int>("sex"); 12 }
那么我们保存的数据保存到哪里去了呢?我们应该如何找到他们,别急,我们下面开始找保持的数据。
打开C:\Users\<user_name>\AppData\Local\Packages\<package>\Settings\settings.dat, user_name对应当前登录的用户名,packpage对应此应用的唯一标识,在Package.appxmanifest中我们可以找到它:
此文件为.dat后缀,我们需要用注册表工具打开它,开始->运行(win+R键),输入Regedit,在打开的窗口里面选择 HKEY_LOCAL_MACHINE,
然后选择文件->加载配置单元,选择settings.dat文件,打开填入项名称,确定之后可以看到保存的数据会显示在其中。
双击name,打开,我们可以看到存储的数据值。
那么我们是否能像wp那样存储一个对象到本地存储呢,答案是否定的。win8中只能存储一些简单类型,如int、bool、string等
下面有一个Person对象:
1 [DataContract] 2 public class Person 3 { 4 [DataMember] 5 public string Name { get; set; } 6 [DataMember] 7 public int Age { get; set; } 8 [DataMember] 9 public int Sex { get; set; } 10 }
进行存储:
1 Person person = new Person() 2 { 3 Name = txtName.Text.Trim(), 4 Age = int.Parse(txtAge.Text.Trim()), 5 Sex = cbxSex.SelectedIndex 6 }; 7 AppDataHelper.Save<Person>("person", person);
此时会报错,提示不支持此类型存储。
那么我们应该如何存储一个对象呢?下面我们将介绍文件存储。
二.文件存储
对于那些比较复杂的数据类型,我们需要将其存储为文件的形式存储在应用中。StorageFile的存储,以文件的形式进行存储存入数据。
新建一个类,LocalFileHelper.cs
存储文件:
1 /// <summary> 2 /// 存储数据/// </summary> 3 /// <typeparam name="T">数据类型</typeparam> 4 /// <param name="fileName">文件名称</param> 5 /// <param name="data">数据</param> 6 /// <returns>无</returns> 7 public async static Task Save<T>(string fileName, T data) 8 { 9 //取得当前程序存放数据的目录 10 StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder; 11 //创建文件,如果文件存在就覆盖 12 StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 13 using (Stream newFileStream = await file.OpenStreamForWriteAsync()) 14 { 15 DataContractSerializer ser = new DataContractSerializer(typeof(T)); 16 ser.WriteObject(newFileStream, data); 17 newFileStream.Dispose(); 18 } 19 }
读取文件:
1 /// <summary> 2 /// 读取数据 3 /// </summary> 4 /// <typeparam name="T">数据类型</typeparam> 5 /// <param name="fileName">文件名称</param> 6 /// <returns>数据</returns> 7 public async static Task<T> Read<T>(string fileName) 8 { 9 T t = default(T); 10 try 11 { 12 StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder; 13 StorageFile file = await folder.GetFileAsync(fileName); 14 if (file == null) 15 return t; 16 Stream newFileStream = await file.OpenStreamForReadAsync(); 17 DataContractSerializer ser = new DataContractSerializer(typeof(T)); 18 t = (T)ser.ReadObject(newFileStream); 19 newFileStream.Dispose(); 20 return t; 21 } 22 catch (Exception) 23 { 24 return t; 25 } 26 }
删除文件:
1 /// <summary> 2 /// 删除文件 3 /// </summary> 4 /// <param name="fileName">文件名称</param> 5 /// <returns>成功true/失败false</returns> 6 public async static Task<bool> Delete(string fileName) 7 { 8 StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder; 9 StorageFile file = await folder.GetFileAsync(fileName); 10 if (file != null) 11 { 12 try 13 { 14 await file.DeleteAsync(); 15 } 16 catch (Exception) 17 { 18 return false; 19 } 20 } 21 return true; 22 }
使用方法:
1 Person person = new Person() 2 { 3 Name = txtName.Text.Trim(), 4 Age = int.Parse(txtAge.Text.Trim()), 5 Sex = cbxSex.SelectedIndex 6 }; 7 8 await LocalFileHelper.Save<Person>("person.xml", person); 9 10 List<Person> list = new List<Person>(); 11 list.Add(person); 12 list.Add(person); 13 await LocalFileHelper.Save<List<Person>>("personList.xml", list); 14 15 16 Person newPerson = await LocalFileHelper.Read<Person>("person.xml"); 17 List<Person> personList = await LocalFileHelper.Read<List<Person>>("personList.xml");
文件在哪里?
同样我们打开C:\Users\user_name\AppData\Local\Packages\package\LocalState文件夹,下面就有我们保持的文件,打开文件,保存文件的内容格式为xml:
<Person xmlns="http://schemas.datacontract.org/2004/07/StorageSample" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Age>27</Age><Name>BetterChaner</Name><Sex>0</Sex></Person>
三.使用Sqlite进行数据存储
Sqlite现已提供对Windows RT和Windows 8 Metro应用的支持.
首先,在工具,选择扩展与更新中,选择联机,在搜索框内输入sqlite,找到SQLite for Window Runtime,下载安装。
安装完成之后重启VS,右击项目添加引用,选择Windows->扩展,找到Mircosoft visual c++ runtime package和sqlite for windows runtime,打勾,确定。
由于目前Sqlite不支持AnyCPU,所以我们将项目改成X64,右击解决方案,属性,修改之。
然后右击引用,选择管理Nuget程序包,联机搜索sqlite-net,下载安装。
我们发现项目工程中多了2个类文件,SQLite.cs和SQLiteAsync.cs
基本操作:
1 //创建数据库 2 string dbRootPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path; 3 SQLiteConnection db = new SQLiteConnection(Path.Combine(dbRootPath, "myApp.sqlite")); 4 5 //创建表 6 db.CreateTable<Person>(); 7 8 //插入一条数据 9 db.Insert(new Person() { Name = "BetterChaner", Age = 27, Sex = 1 }); 10 11 //插入多条数据 12 List<Person> list = new List<Person>(); 13 list.Add(new Person() { Name = "Zhangsan", Age = 27, Sex = 1 }); 14 list.Add(new Person() { Name = "Lisi", Age = 32, Sex = 0 }); 15 list.Add(new Person() { Name = "Wangwu", Age = 24, Sex = 1 }); 16 db.InsertAll(list); 17 18 //查询数据 19 List<Person> list2 = db.Query<Person>("select * from Person"); 20 21 //更新数据 22 SQLiteCommand cmd = db.CreateCommand("update Person set Age=21 where Name='Lisi'"); 23 cmd.ExecuteNonQuery(); 24 25 //删除一条数据 26 db.Delete(new Person() { Name = "Zhangsan", Age = 27, Sex = 1 }); 27 //删除全部数据 28 db.DeleteAll<Person>();
数据存储的位置为:C:\Users\<user_name>\AppData\Local\Packages\<package>\LocalState\文件夹下的myApp.sqlite
四.SqlCE
有了Sqilte,SqlCE不太经常会用到了,在这里就不写出实例了,与wp中类似。
小结
以上为windows store app开发中可以使用的几种存储数据的方式,可以根据数据大小、作用以及类型选择应该使用哪一种存储方式。