《深入浅出Windows Phone 8应用开发》之程序联系人存储 
  程序联系人存储是第三方的应用程序创建的联系人数据,这些联系人的数据也可以在手机的通讯录里面进行显示,但是它们是由创建这些联系人数据的第三方应用程序所管理的。联系人数据的归属应用程序可以设置这些联系人数据的系统和其他程序的访问权限,对属于它自己的联系人具有增删改的权限,并且一旦用户卸载了联系人数据归属应用程序,这些联系人也会被删除掉。程序联系人存储的API在空间Windows.Phone.PersonalInformation下,下面来看一下如何去使用这些API来操作联系人。 
 
ContactStore类和StoredContact类 
  ContactStore类表示一个Windows Phone应用程序的自定义联系人存储,它是应用程序存储的一个管理者,负责管理应用程序所创建的联系人。ContactStore类的主要成员如表15.9所示。StoredContact类表示一个应用程序自定义的联系人存储,它继承了IContactInformation接口,所有由应用程序创建的联系人都是一个StoredContact类的对象。StoredContact类的主要成员如表15.10所示。 
  表15.9 ContactStore类的主要成员 
 
  成员 
 
 |   说明 
 
 |    public   ulong RevisionNumber { get; } 
 
 |   联系人存储的版本号 
 
 |    public   ContactQueryResult CreateContactQuery() 
 
 |   创建一个默认的联系人查询,返回ContactQueryResult对象,包含了存储中的联系人 
 
 |    public   ContactQueryResult CreateContactQuery(ContactQueryOptions options) 
 
 |   创建一个自定义的联系人查询,返回ContactQueryResult对象,包含了存储中的联系人 
 
 |    public   static IAsyncOperation CreateOrOpenAsync() 
 
 |   异步方法创建或者打开应用程序的自定义联系人存储,假如存储不存在将创建一个存储 
 
 |    public   static IAsyncOperation   CreateOrOpenAsync(ContactStoreSystemAccessMode access,   ContactStoreApplicationAccessMode sharing) 
 
 |   异步方法创建或者打开应用程序的自定义联系人存储,假如存储不存在将创建一个存储,返回当前的联系人存储对象 
  access:联系人是否可以在手机系统通讯录里面进行编辑还是只能在应用程序中创建 
  sharing:是否存储的联系人所有属性都可以在另外的应用程序里面进行访问 
 
 |    public   IAsyncAction DeleteAsync() 
 
 |   异步方法删除应用程序的联系人存储 
 
 |    public   IAsyncAction DeleteContactAsync(string id) 
 
 |   异步方法通过联系人的ID删除应用程序里面存储的联系人 
 
 |    public   IAsyncOperation FindContactByIdAsync(string id) 
 
 |   异步方法通过ID查找应用程序的联系人,返回StoredContact对象 
 
 |    public   IAsyncOperation FindContactByRemoteIdAsync(string id) 
 
 |   异步方法通过remote ID查找应用程序的联系人,返回StoredContact对象 
 
 |    public   IAsyncOperation   GetChangesAsync(ulong baseREvisionNumber) 
 
 |   异步方法通过联系人的版本号获取联系人改动记录 
 
 |    public   IAsyncOperation   LoadExtendedPropertiesAsync() 
 
 |   异步方法加载应用程序联系人的扩展属性Map表 
 
 |    public   IAsyncAction SaveExtendedPropertiesAsync(IReadOnlyDictionary data) 
 
 |   异步方法保存应用程序联系人的扩展属性Map表 
 
 |     表15.10 StoredContact类的主要成员 
 
  成员 
 
 |   说明 
 
 |    public   StoredContact(ContactStore store) 
 
 |   通过当前应用程序的ContactStore来初始化一个StoredContact对象 
 
 |    public   StoredContact(ContactStore store, ContactInformation contact) 
 
 |   通过ContactStore对象和ContactInformation对象来创建一个StoredContact对象,StoredContact对象的信息由ContactInformation对象来提供 
 
 |    public   string DisplayName { get; set; } 
 
 |   获取或设置一个存储联系人的显示名称 
 
 |    public   IRandomAccessStreamReference DisplayPicture { get; } 
 
 |   获取一个存储联系人的图片 
 
 |    public   string FamilyName { get; set; } 
 
 |   获取或设置一个存储联系人的家庭姓 
 
 |    public   string GivenName { get; set; } 
 
 |   获取或设置一个存储联系人的名字 
 
 |    public   string HonorificPrefix { get; set; } 
 
 |   获取或设置一个存储联系人的尊称前缀 
 
 |    public   string HonorificSuffix { get; set; } 
 
 |   获取或设置一个存储联系人的尊称后缀 
 
 |    public   string Id { get; } 
 
 |   获取应用程序存储联系人的ID 
 
 |    public   string RemoteId { get; set; } 
 
 |   获取或设置应用程序联系人的RemoteId 
 
 |    public   ContactStore Store { get; } 
 
 |   获取当前应用程序联系人所在的联系存储对象 
 
 |    public   IAsyncOperation GetDisplayPictureAsync() 
 
 |   获取一个存储联系人的图片 
 
 |    public   IAsyncOperation GetExtendedPropertiesAsync() 
 
 |   异步方法获取联系人的扩展属性Map表 
 
 |    public   IAsyncOperation GetPropertiesAsync() 
 
 |   异步方法获取联系人的已知属性Map表 
 
 |    public   IAsyncAction ReplaceExistingContactAsync(string id) 
 
 |   异步方法使用当前的联系儿人来替换联系人存储中某个ID的联系人 
 
 |    public   IAsyncAction SaveAsync() 
 
 |   异步方法保存当前的联系人到联系人存储中 
 
 |    public   IAsyncAction SetDisplayPictureAsync(IInputStream stream) 
 
 |   异步方法保存当前的联系人的图片 
 
 |    public   IAsyncOperation ToVcardAsync() 
 
 |   异步方法把当前的联系人转化为VCard信息流 
 
 |  
  
15.3.2 程序联系人的新增 
  新增程序联系人需要先创建或者打开程序的联系人存储ContactStore,并且可以设置该程序联系人存储的被访问权限。创建的代码如下: 
  ContactStore conStore = await ContactStore.CreateOrOpenAsync(); 
  联系人存储对于系统通讯和其他程序的都有权限的限制,ContactStoreSystemAccessMode枚举表示手机系统通讯录对应用程序联系人的访问权限,有ReadOnly只读权限和ReadWrite读写两个权限,ContactStoreApplicationAccessMode枚举表示第三方应用程序对应用程序联系人的访问权限类型,有LimitedReadOnly限制只读权限和ReadOnly只读权限。上面的代码创建联系人存储的代码是默认用了最低的访问权限来来创建联系人存储,即联系人对于系统通讯录是只读的权限,对于其他程序的访问权限是限制只读权限。下面来看一下自定义权限的创建联系人存储。 
  //创建一个系统通讯可以读写和其他程序只读的联系人存储 
  ContactStore conStore = await ContactStore.CreateOrOpenAsync(ContactStoreSystemAccessMode.ReadWrite, ContactStoreApplicationAccessMode.ReadOnly); 
  接下来看一下如何创建一个联系人: 
      1.第一种方式直接通过联系人存储创建联系人 
  //创建或者打开联系人存储 
  ContactStore conStore = await ContactStore.CreateOrOpenAsync(); 
  //保存联系人 
  StoredContact storedContact = new StoredContact(conStore); 
  // 设置联系人的展示名称 
  storedContact.DisplayName = "展示名称"; 
  //保存联系人 
  await storedContact.SaveAsync(); 
  2.第二种方式通过ContactInformation类对象创建联系人 
  ContactInformation类表示一个非系统存储中联系人的联系人信息。ContactInformation类的主要成员如表15.11所示。 
  //创建一个ContactInformation类 
  ContactInformation conInfo = new ContactInformation(); 
  // 获取ContactInformation类的属性map表 
  var properties = await conInfo.GetPropertiesAsync(); 
  //添加电话属性 
  properties.Add(KnownContactProperties.Telephone, "123456"); 
  //添加名字属性 
  properties.Add(KnownContactProperties.GivenName, "名字"); 
  //创建或者打开联系人存储 
  ContactStore conStore = await ContactStore.CreateOrOpenAsync(); 
  //保存联系人 
  StoredContact storedContact = new StoredContact(conStore, conInfo); 
  //保存联系人 
  await storedContact.SaveAsync(); 
  表15.11 ContactInformation类主要成员 
 
  成员 
 
 |   说明 
 
 |    ContactInformation() 
 
 |   初始化 
 
 |    string DisplayName 
 
 |   联系人的显示名字 
 
 |    IRandomAccessStreamReference   DisplayPicture 
 
 |   联系人图片信息 
 
 |    string FamilyName 
 
 |   联系人姓 
 
 |    string GivenName 
 
 |   名字 
 
 |    string HonorificPrefix 
 
 |   尊称前缀 
 
 |    string HonorificSuffix 
 
 |   尊称后缀 
 
 |    IAsyncOperation   GetDisplayPictureAsync() 
 
 |   异步获取联系人图片 
 
 |    IAsyncOperation GetPropertiesAsync() 
 
 |   异步获取联系人的Map表信息 
 
 |    IAsyncOperation   ParseVcardAsync(IInputStream vcard) 
 
 |   异步解析一个VCard数据流为ContactInformation对象 
 
 |    IAsyncAction   SetDisplayPictureAsync(IInputStream stream) 
 
 |   异步设置联系人的图片通过图片数据流 
 
 |    IAsyncOperation   ToVcardAsync() 
 
 |   异步转换ContactInformation对象为一个VCard信息流 
 
 |  
  
程序联系人的查询 
  联系人查询也需要创建联系人存储,创建联系人存储的形式和联系人新增是一样的。联系人查询是通过ContactStore的CreateContactQuery方法来创建一个查询,可以查询的参数ContactQueryOptions来设置查询返回的结果和排序的规则,创建的查询时ContactQueryResult类型。可以通过ContactQueryResult类的GetContactsAsync异步方法获取联系人存储中的联系人列表和通过GetCurrentQueryOptions方法获取当前的查询条件。下面来看创建联系人查询的代码如下: 
  conStore = await ContactStore.CreateOrOpenAsync(); 
  ContactQueryResult conQueryResult = conStore.CreateContactQuery(); 
  uint count = await conQueryResult.GetContactCountAsync(); 
  IReadOnlyList conList = await conQueryResult.GetContactsAsync(); 
 
程序联系人的编辑 
  联系人编辑删除也需要创建联系人存储,创建联系人存储的形式和联系人新增是一样的。联系人的编辑需要首先要获取要编辑的联系人,获取编辑的联系人可以通过联系人的id或者remoteid来获取,获取到的联系人是一个StoredContact对象,通过修改该对象的属性,然后再调用SaveAsync保存方法就可以实现编辑联系人了。删除联系人的可以分为删除一个联系人和删除所有的联系人,删除一个联系人的可以通过联系人的id然后调用ContactStore的DeleteContactAsync方法来进行删除,如果要删除所有的联系人那么就要调用ContactStore的DeleteAsync方法。联系人的新增,编辑和删除都会有相关的操作记录,GetChangesAsync方法来获取联系人的修改记录。下面来看一下修改一个联系人的代码: 
    ContactStore conStore = await ContactStore.CreateOrOpenAsync();  
    StoredContact   storCon = await conStore.FindContactByIdAsync(id);  
  var properties = await storCon.GetPropertiesAsync(); 
    properties[KnownContactProperties.Telephone] = "12345678";  
  await storCon.SaveAsync(); 
 
程序联系人的删除 
  删除联系人的可以分为删除一个联系人和删除所有的联系人,删除一个联系人的可以通过联系人的id然后调用ContactStore的DeleteContactAsync方法来进行删除,如果要删除所有的联系人那么就要调用ContactStore的DeleteAsync方法。联系人的新增,编辑和删除都会有相关的操作记录,GetChangesAsync方法来获取联系人的修改记录。下面来看一下删除一个联系人的代码: 
    ContactStore conStore = await ContactStore.CreateOrOpenAsync();  
    await conStore.DeleteContactAsync (id);  
    await conStore.DeleteAsync ();  
 
实例演示联系人存储的使用 
  下面给出查询日程安排的示例:查询手机里面所有的日程安排信息。 
代码清单15-3:联系人存储的增删改(源代码:第15章\Examples_15_3) 
  MainPage.xaml文件主要代码:联系人新增页面 
 
 
 
         
 
 
 
 
 
 
 
 
 
  MainPage.xaml.cs文件主要代码 
 
 
 
        // 新增一个联系人 
private async void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
if (name.Text != "" && phone.Text != "") 
{ 
try 
{ 
// 创建一个联系人的信息对象 
ContactInformation conInfo = new ContactInformation(); 
// 获取联系人的属性字典 
var properties = await conInfo.GetPropertiesAsync(); 
// 添加联系人的属性 
                    properties.Add(KnownContactProperties.Telephone, phone.Text); 
properties.Add(KnownContactProperties.GivenName, name.Text); 
// 创建或者打开联系人存储 
ContactStore conStore = await ContactStore.CreateOrOpenAsync(); 
StoredContact storedContact = new StoredContact(conStore, conInfo); 
// 保存联系人 
await storedContact.SaveAsync(); 
MessageBox.Show("保存成功"); 
} 
catch (Exception ex) 
{ 
MessageBox.Show("保存失败,错误信息:" + ex.Message); 
} 
} 
else 
{ 
MessageBox.Show("名字或电话不能为空"); 
} 
} 
// 跳转到联系人列表页面 
private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
NavigationService.Navigate(new Uri("/ContactsList.xaml", UriKind.Relative)); 
} 
  ContactsList.xaml文件主要代码:联系人列表页面 
 
 
 
         
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  ContactsList.xaml.cs文件主要代码 
 
 
 
        private ContactStore conStore;//联系人存储 
public ContactsList() 
{ 
InitializeComponent(); 
} 
// 进入页面事件 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
GetContacts(); 
base.OnNavigatedTo(e); 
} 
// 获取联系人列表 
async private void GetContacts() 
{ 
conStore = await ContactStore.CreateOrOpenAsync(); 
ContactQueryResult conQueryResult = conStore.CreateContactQuery(); 
// 查询联系人 
IReadOnlyList conList = await conQueryResult.GetContactsAsync(); 
List list = new List(); 
foreach (StoredContact storCon in conList) 
{ 
var properties = await storCon.GetPropertiesAsync(); 
list.Add( 
new Item 
{ 
Name = storCon.FamilyName + storCon.GivenName, 
Id = storCon.Id, 
Phone = properties[KnownContactProperties.Telephone].ToString() 
}); 
} 
conListBox.ItemsSource = list; 
} 
// 删除联系人事件处理 
private async void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
Button deleteButton = sender as Button; 
Item deleteItem = deleteButton.DataContext as Item; 
await conStore.DeleteContactAsync(deleteItem.Id); 
GetContacts();     
} 
// 跳转到编辑联系人页面 
private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
Button deleteButton = sender as Button; 
Item editItem = deleteButton.DataContext as Item; 
NavigationService.Navigate(new Uri("/EditContact.xaml?Id=" + editItem.Id, UriKind.Relative)); 
} 
} 
// 自定义绑定的联系人数据对象 
class Item 
{ 
public string Name { get; set; } 
public string Id { get; set; } 
public string Phone { get; set; } 
} 
  EditContact.xaml文件主要代码:联系人编辑页面  
 
 
 
         
 
 
 
 
 
 
 
 
  EditContact.xaml.cs文件主要代码 
 
 
 
        private string conId = ""; 
private ContactStore conStore;//联系人数据存储 
private StoredContact storCon; //联系人对象 
private IDictionary properties;//联系人属性字典 
public EditContact() 
{ 
InitializeComponent();   
} 
// 进入页面事件处理 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
// 通过联系人的id获取联系人的信息 
if (NavigationContext.QueryString.ContainsKey("Id")) 
{ 
conId = NavigationContext.QueryString["Id"].ToString(); 
GetContact(conId); 
} 
base.OnNavigatedTo(e); 
} 
// 保存编辑的联系人 
private async void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
if (name.Text != "" && phone.Text != "") 
{ 
storCon.GivenName = name.Text; 
properties[KnownContactProperties.Telephone] = phone.Text; 
await storCon.SaveAsync();//保存联系人 
NavigationService.GoBack(); //返回上一个页面 
            } 
else 
{ 
MessageBox.Show("名字或者电话不能为空"); 
} 
} 
// 获取需要编辑的联系人信息 
async private void GetContact(string id) 
{ 
conStore = await ContactStore.CreateOrOpenAsync(); 
storCon = await conStore.FindContactByIdAsync(id); 
properties = await storCon.GetPropertiesAsync(); 
name.Text = storCon.GivenName; 
phone.Text = properties[KnownContactProperties.Telephone].ToString(); 
} 
phone.Text = properties[KnownContactProperties.Telephone].ToString(); 
} 
  程序的运行效果如图所示 
  
 
 
 
 |