老周的部落格http://blog.csdn.net/tcjiaan,轉載請註明原作者和出處。
上回我們討論了如何從連絡人選取器中選擇連絡人記錄。但,我們也許會發現一個問題,我們都知道,我們選擇的連絡人都是通過Microsoft帳號從雲端服務器取出來的,那麼,如果我有自己的連絡人資料呢?比如,保豐在本機資料檔案中的,或者從我的Web服務中擷取的連絡人呢?那這種情況下,還能用連絡人選取器來選擇嗎?
答案當然是肯定的,在Windows Store公開的API中,是允許我們對某些特殊的應用程式或UI進行自訂擴充,如前面我們提到的開啟檔案UI,儲存檔案UI,以及選取連絡人資訊UI都是可以擴充的。
這些擴充使用起來不難,只是剛剛接觸的話,可能你會感到有些複雜,所以,還是那句話:熟能生巧,實踐才能找到真理。
我們看看這個選取器是如何被擴充的,如果你安裝過大智慧軟體或者我們今天的應用,在選在連絡人時,會看到下面的介面。
也就是說,這些擴充的應用,都整合到連絡人選取器中了。
不多說了,Action!我們一邊動手一邊討論吧。
1、啟動VS for Win8,隨便哪個版本,支援就行。建立項目,選擇你喜歡的語言(C#),在模板中選擇空白頁面應用程式。
2、這樣吧,我們把核心知識放到前面吧,先做好護展選取器的部分吧。
開啟“方案總管”視窗,在項目上右擊,在彈出的菜單中選擇“添加”-“建立項”,接著彈出一個建立項視窗,選擇空白頁,我們就命名為MyContactsPage.xaml。
這個頁面不算複雜,只放一個ListView控制項,這個頁面就會成為我們啟動連絡人選取器時顯示的列表。
<Page x:Class="MyApp.MyContactsPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <CollectionViewSource x:Key="cvs" x:Name="cvs"/> </Page.Resources> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <ListView Name="lvContacts" ItemsSource="{Binding Source={StaticResource cvs}}" SelectionChanged="lvContacts_SelectionChanged_1" SelectionMode="Multiple" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollMode="Auto"> <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapGrid Orientation="Vertical" MaximumRowsOrColumns="3" ItemWidth="380" /> </ItemsPanelTemplate> </ListView.ItemsPanel> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical" Margin="8"> <TextBlock FontWeight="Bold" FontSize="20" Text="{Binding Name}" /> <StackPanel Orientation="Horizontal"> <TextBlock FontSize="18" Text="手機號碼:"/> <TextBlock FontSize="18" Text="{Binding CellPhoneNo}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock FontSize="18" Text="Email:"/> <TextBlock FontSize="18" Text="{Binding EmailAddress}"/> </StackPanel> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid></Page>
注意頁面的資源部分,我聲明了一個CollectionViewSource,而ListView的資料來源正是從它裡面取,所以在ListView聲明的時候,我們用Binding來擷取資料。
<ListView Name="lvContacts" ItemsSource="{Binding Source={StaticResource cvs}}" ..........
也就是說,我們在後台代碼中只需要為CollectionViewSource賦值即可。
3、在XAML視圖中右擊,從彈出的菜單中選擇“查看代碼”,切換到程式碼檢視。
首先,我們需要定義一個自訂連絡人類。這是我們用來測試的樣本資料。
public class CustContact { /// <summary> /// 連絡人名字 /// </summary> public string Name { get; set; } /// <summary> /// 連絡人手機號碼 /// </summary> public string CellPhoneNo { get; set; } /// <summary> /// 連絡人電郵地址 /// </summary> public string EmailAddress { get; set; } /// <summary> /// 擷取測試資料來源 /// </summary> /// <returns></returns> public static ObservableCollection<CustContact> GetContactSamples() { ObservableCollection<CustContact> mcList = new ObservableCollection<CustContact>(); mcList.Add(new CustContact { Name = "陳大冤", CellPhoneNo = "1388888552", EmailAddress = "ssdi@qq.com" }); mcList.Add(new CustContact { Name = "劉產", CellPhoneNo = "13712546810", EmailAddress = "zhe254@126.com" }); mcList.Add(new CustContact { Name = "鬼棟樑", CellPhoneNo = "18925445525", EmailAddress = "fuckdog@foxmail.com" }); mcList.Add(new CustContact { Name = "小氣鬼", CellPhoneNo = "13628845781", EmailAddress= "ass054@21cn.com" }); mcList.Add(new CustContact { Name = "吳狗", CellPhoneNo = "13425546387", EmailAddress = "laobin@foxmail.com" }); mcList.Add(new CustContact { Name = "小趙", CellPhoneNo = "159999558462", EmailAddress = "hxdok@163.com" }); mcList.Add(new CustContact { Name = "老吹", CellPhoneNo = "1382601021", EmailAddress = "gaosu22@foxmail.com" }); mcList.Add(new CustContact { Name = "史珍香", CellPhoneNo = "10101010110", EmailAddress = "25466887@qq.com" }); mcList.Add(new CustContact { Name = "杜子騰", CellPhoneNo = "10084", EmailAddress = "bageyalu@21cn.com" }); mcList.Add(new CustContact { Name = "B哥", CellPhoneNo = "15525863314", EmailAddress = "ruxinde@126.com" }); return mcList; } }
4、處理ListView的SelectionChanged事件,以響應使用者的選擇操作。
private void lvContacts_SelectionChanged_1(object sender, SelectionChangedEventArgs e) { if (pkUI == null) { return; } ContactFieldFactory ctFactory = new ContactFieldFactory(); // 將選中的項添加到已選連絡人清單 foreach (var itemAdded in e.AddedItems) { CustContact c = (CustContact)itemAdded; if (!pkUI.ContainsContact(c.Name)) { Contact contact = new Contact(); contact.Name = c.Name; // 建立手機號碼和電郵地址欄位 ContactField phoneNoField = ctFactory.CreateField(c.CellPhoneNo, ContactFieldType.PhoneNumber); ContactField emailField = ctFactory.CreateField(c.EmailAddress, ContactFieldType.Email); // 別忘了把欄位添加到連絡人中 contact.Fields.Add(phoneNoField); contact.Fields.Add(emailField); pkUI.AddContact(c.Name, contact); } } // 將未選中的連絡人從已選列表中刪除 foreach (var removedItem in e.RemovedItems) { CustContact ct = (CustContact)removedItem; if (pkUI.ContainsContact(ct.Name)) { pkUI.RemoveContact(ct.Name); } } }
已經選擇的項就添加到選取器的連絡人清單中,而沒有被選中的就從連絡人清單中移除。新增連絡人...列表時(AddContact方法調用)有一個id參數,我們可以用連絡人的名字作為其id值。
5、為了不影響產生的App代碼,同時也方便我們維護,還是另起一個App類,並重寫OnActivated方法。
sealed partial class App : Application { protected override void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs args) { // 判斷是否連絡人選取器啟用本應用程式 if (args.Kind == Windows.ApplicationModel.Activation.ActivationKind.ContactPicker) { Frame root = Window.Current.Content as Frame; // 判斷當前視窗是否有內容 if (root == null) { root = new Frame(); // 導航到選擇連絡人的頁面 root.Navigate(typeof(MyContactsPage), (ContactPickerActivatedEventArgs)args); // 將此Frame設定為當前視窗的內容 Window.Current.Content = root; } Window.Current.Activate(); //啟用當前視窗 } } }
因為我們在頁面的代碼中要操作ContactPickerUI對象,所以將參數args傳遞到頁面導航。
完整的代碼如下。
using System;using System.Collections.Generic;using System.IO;using System.Linq;using Windows.Foundation;using Windows.Foundation.Collections;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Data;using Windows.UI.Xaml.Input;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Navigation;using System.Collections.ObjectModel;using Windows.ApplicationModel.Activation;using Windows.ApplicationModel.Contacts;using Windows.ApplicationModel.Contacts.Provider;// “空白頁”項目範本在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介紹namespace MyApp{ /// <summary> /// 可用於自身或導航至 Frame 內部的空白頁。 /// </summary> public sealed partial class MyContactsPage : Page { ContactPickerUI pkUI = null; public MyContactsPage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { this.cvs.Source = CustContact.GetContactSamples(); if (e.Parameter != null) { if (e.Parameter is ContactPickerActivatedEventArgs) { this.pkUI = ((ContactPickerActivatedEventArgs)e.Parameter).ContactPickerUI; } } } private void lvContacts_SelectionChanged_1(object sender, SelectionChangedEventArgs e) { if (pkUI == null) { return; } ContactFieldFactory ctFactory = new ContactFieldFactory(); // 將選中的項添加到已選連絡人清單 foreach (var itemAdded in e.AddedItems) { CustContact c = (CustContact)itemAdded; if (!pkUI.ContainsContact(c.Name)) { Contact contact = new Contact(); contact.Name = c.Name; // 建立手機號碼和電郵地址欄位 ContactField phoneNoField = ctFactory.CreateField(c.CellPhoneNo, ContactFieldType.PhoneNumber); ContactField emailField = ctFactory.CreateField(c.EmailAddress, ContactFieldType.Email); // 別忘了把欄位添加到連絡人中 contact.Fields.Add(phoneNoField); contact.Fields.Add(emailField); pkUI.AddContact(c.Name, contact); } } // 將未選中的連絡人從已選列表中刪除 foreach (var removedItem in e.RemovedItems) { CustContact ct = (CustContact)removedItem; if (pkUI.ContainsContact(ct.Name)) { pkUI.RemoveContact(ct.Name); } } } } public class CustContact { /// <summary> /// 連絡人名字 /// </summary> public string Name { get; set; } /// <summary> /// 連絡人手機號碼 /// </summary> public string CellPhoneNo { get; set; } /// <summary> /// 連絡人電郵地址 /// </summary> public string EmailAddress { get; set; } /// <summary> /// 擷取測試資料來源 /// </summary> /// <returns></returns> public static ObservableCollection<CustContact> GetContactSamples() { ObservableCollection<CustContact> mcList = new ObservableCollection<CustContact>(); mcList.Add(new CustContact { Name = "陳大冤", CellPhoneNo = "1388888552", EmailAddress = "ssdi@qq.com" }); mcList.Add(new CustContact { Name = "劉產", CellPhoneNo = "13712546810", EmailAddress = "zhe254@126.com" }); mcList.Add(new CustContact { Name = "鬼棟樑", CellPhoneNo = "18925445525", EmailAddress = "fuckdog@foxmail.com" }); mcList.Add(new CustContact { Name = "小氣鬼", CellPhoneNo = "13628845781", EmailAddress= "ass054@21cn.com" }); mcList.Add(new CustContact { Name = "吳狗", CellPhoneNo = "13425546387", EmailAddress = "laobin@foxmail.com" }); mcList.Add(new CustContact { Name = "小趙", CellPhoneNo = "159999558462", EmailAddress = "hxdok@163.com" }); mcList.Add(new CustContact { Name = "老吹", CellPhoneNo = "1382601021", EmailAddress = "gaosu22@foxmail.com" }); mcList.Add(new CustContact { Name = "史珍香", CellPhoneNo = "10101010110", EmailAddress = "25466887@qq.com" }); mcList.Add(new CustContact { Name = "杜子騰", CellPhoneNo = "10084", EmailAddress = "bageyalu@21cn.com" }); mcList.Add(new CustContact { Name = "B哥", CellPhoneNo = "15525863314", EmailAddress = "ruxinde@126.com" }); return mcList; } } sealed partial class App : Application { protected override void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs args) { // 判斷是否連絡人選取器啟用本應用程式 if (args.Kind == Windows.ApplicationModel.Activation.ActivationKind.ContactPicker) { Frame root = Window.Current.Content as Frame; // 判斷當前視窗是否有內容 if (root == null) { root = new Frame(); // 導航到選擇連絡人的頁面 root.Navigate(typeof(MyContactsPage), (ContactPickerActivatedEventArgs)args); // 將此Frame設定為當前視窗的內容 Window.Current.Content = root; } Window.Current.Activate(); //啟用當前視窗 } } }}
6、回過頭來,我們在看看首頁。
開啟MainPage.xaml,參考以下XAML。
<Page x:Class="MyApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal"> <Button Margin="15,12,7,6" Content="選擇連絡人" Click="onSelect"/> <TextBlock Name="tbMsg" Margin="8,23,0,6" FontSize="18"/> </StackPanel> <ListView Name="lv" Grid.Row="1" Margin="7"> <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3" ItemWidth="350"/> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView> </Grid></Page>
7、後台代碼如下。
using System;using System.Collections.Generic;using System.IO;using System.Linq;using Windows.Foundation;using Windows.Foundation.Collections;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Data;using Windows.UI.Xaml.Input;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Navigation;using Windows.ApplicationModel.Contacts;// “空白頁”項目範本在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介紹namespace MyApp{ /// <summary> /// 可用於自身或導航至 Frame 內部的空白頁。 /// </summary> public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } private async void onSelect(object sender, RoutedEventArgs e) { ContactPicker cp = new ContactPicker(); IReadOnlyList<ContactInformation> contactlist = await cp.PickMultipleContactsAsync(); if (contactlist != null ) { foreach (var item in contactlist) { string msg = ""; msg += item.Name + "\n"; //手機號碼 foreach (var fds in item.PhoneNumbers) { msg += string.Format("{0} : {1}", fds.Name, fds.Value) + "\n"; } //電郵地址 foreach (var emfds in item.Emails) { msg += string.Format("{0} : {1}", emfds.Name, emfds.Value) + "\n"; } this.lv.Items.Add(msg); this.tbMsg.Text = string.Format("你已選擇了{0}條連絡人記錄。", contactlist.Count); } } } }}
這個不用解釋了,和上一篇文章中是一樣的。
8、開啟資訊清單檔,切換到“聲明”選項卡,從下拉式清單中選擇“連絡人選取器”,點擊右邊的“添加”按鈕。
現在,可以運行應用了。點擊選擇連絡人。
選擇後,點確定。回到首頁面,就看到我們剛才選擇的連絡人了。
本文內容可能不太好理解,所以,稍後我會把原始碼上傳到資源。
最後,祝大家中秋節快樂。