posts - 433, comments - 9530, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

重新想象 Windows 8 Store Apps (27) - 选取器: 联系人选取窗口, 自定义联系人选取窗口

Posted on 2013-05-20 08:26 webabcd 阅读(...) 评论(...) 编辑 收藏

[源码下载]


重新想象 Windows 8 Store Apps (27) - 选取器: 联系人选取窗口, 自定义联系人选取窗口



作者:webabcd


介绍
重新想象 Windows 8 Store Apps 之 选取器

  • ContactPicker - 联系人选取器
  • ContactPickerUI - 自定义联系人选取器



示例
演示如何通过 ContactPicker 选择一个或多个联系人,以及如何开发自定义联系人选取器

1、 开发一个自定义联系人选取器
Picker/MyContactPicker.xaml

<Page
    x:Class="XamlDemo.Picker.MyContactPicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Picker"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <TextBlock Name="lblMsg" FontSize="14.667" />

            <Button Name="btnAddContract" Content="增加一个联系人" Click="btnAddContract_Click" Margin="0 10 0 0" />

        </StackPanel>
    </Grid>
</Page>

Picker/MyContactPicker.xaml.cs

/*
 * 演示如何开发自定义的联系人选取器
 * 
 * 1、在 Package.appxmanifest 中新增一个“联系人选取器”声明,并做相关配置
 * 2、在 App.xaml.cs 中 override void OnActivated(IActivatedEventArgs args),以获取联系人选取器的相关信息
 * 
 * ContactPickerActivatedEventArgs - 通过“联系人选取器”激活应用程序时的事件参数
 *     ContactPickerUI - 获取 ContactPickerUI 对象
 *     PreviousExecutionState, Kind, SplashScreen - 各种激活 app 的方式的事件参数基本上都有这些属性,就不多说了
 * 
 * ContactPickerUI - 自定义联系人选取器的帮助类
 *     SelectionMode - 获取由 ContactPicker(调用者)设置的 SelectionMode 属性
 *     DesiredFields - 获取由 ContactPicker(调用者)设置的 DesiredFields 属性
 *     AddContact(string id, Contact contact) - 选取一个联系人
 *         id - 联系人标识
 *         contact - 一个 Contact 对象
 *     RemoveContact() - 删除指定标识的联系人
 *     ContainsContact() - 指定标识的联系人是否已被选取
 *     ContactRemoved - 移除一个已被选取的联系人时所触发的事件
 *     
 * Contact - 返回给调用者的联系人对象
 *     Name - 名称
 *     Thumbnail - 缩略图
 *     Fields - 联系人的字段数据,每一条数据都是一个实现了 IContactField 接口的对象
 *     
 * ContactField - 实现了 IContactField 接口,用于描述联系人的某一个字段数据
 *     Type - 字段类型(ContactFieldType 枚举)
 *         Email, PhoneNumber, Location, InstantMessage, Custom
 *     Category - 字段类别(ContactFieldCategory 枚举)
 *         None, Home, Work, Mobile, Other
 *     Value - 字段的值
 */

using System;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Contacts.Provider;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.ApplicationModel.Contacts;
using Windows.Storage.Streams;
using Windows.UI.Core;

namespace XamlDemo.Picker
{
    public sealed partial class MyContactPicker : Page
    {
        private ContactPickerUI _contactPickerUI;

        public MyContactPicker()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 获取 ContactPickerUI 对象
            var contactPickerActivated = e.Parameter as ContactPickerActivatedEventArgs;
            _contactPickerUI = contactPickerActivated.ContactPickerUI;

            _contactPickerUI.ContactRemoved += _contactPickerUI_ContactRemoved;   
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            _contactPickerUI.ContactRemoved -= _contactPickerUI_ContactRemoved;
        }

        // 从选取缓冲区移除后
        async void _contactPickerUI_ContactRemoved(ContactPickerUI sender, ContactRemovedEventArgs args)
        {
            // 注意:无法直接得知 ContactPickerUI 是单选模式还是多选模式,需要判断当添加了一个联系人后,再添加一个联系人,如果系统会自动移除前一个联系人,则说明是单选模式
            await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                lblMsg.Text += "removed contact: " + args.Id;
                lblMsg.Text += Environment.NewLine;
            });
        }

        private void btnAddContract_Click(object sender, RoutedEventArgs e)
        {
            Random random = new Random();

            // 构造一个 Contact 对象
            Contact contact = new Contact();
            contact.Name = "webabcd " + random.Next(1000, 10000).ToString();
            contact.Fields.Add(new ContactField(random.Next(1000, 10000).ToString(), ContactFieldType.Email, ContactFieldCategory.Home));
            contact.Fields.Add(new ContactField(random.Next(1000, 10000).ToString(), ContactFieldType.Email, ContactFieldCategory.Work));
            contact.Fields.Add(new ContactField(random.Next(1000, 10000).ToString(), ContactFieldType.PhoneNumber, ContactFieldCategory.Home));
            contact.Fields.Add(new ContactField(random.Next(1000, 10000).ToString(), ContactFieldType.PhoneNumber, ContactFieldCategory.Work));
            contact.Thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));

            string id = Guid.NewGuid().ToString();

            // 向选取缓冲区新增一个联系人
            switch (_contactPickerUI.AddContact(id, contact))
            {
                case AddContactResult.Added: // 已被成功添加
                    lblMsg.Text += "added contact: " + id;
                    lblMsg.Text += Environment.NewLine;
                    break;
                case AddContactResult.AlreadyAdded: // 选取缓冲区已有此联系人
                    lblMsg.Text += "already added contact: " + id;
                    lblMsg.Text += Environment.NewLine;
                    break;
                case AddContactResult.Unavailable: // 无效联系人
                    lblMsg.Text += "unavailable contact: " + id;
                    lblMsg.Text += Environment.NewLine;
                    break;
            }
        }
    }
}


2、判断程序是否是由联系人选取器激活,在 App.xaml.cs 中 override void OnActivated(IActivatedEventArgs args)
App.xaml.cs

protected override void OnActivated(IActivatedEventArgs args)
{
    // 通过联系人选取器激活应用程序时
    if (args.Kind == ActivationKind.ContactPicker)
    {
        ContactPickerActivatedEventArgs contactPickerArgs = args as ContactPickerActivatedEventArgs;

        Frame rootFrame = new Frame();
        rootFrame.Navigate(typeof(MainPage), contactPickerArgs);
        Window.Current.Content = rootFrame;

        Window.Current.Activate();
    }
}


3、通过联系人选取器选择联系人。注:如果需要激活自定义的联系人选取器,请在弹出的选取器窗口的左上角选择对应 Provider
Picker/ContactPickerDemo.xaml

<Page
    x:Class="XamlDemo.Picker.ContactPickerDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlDemo.Picker"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="120 0 0 0">

            <TextBlock Name="lblMsg" FontSize="14.667" />

            <Image Name="imgThumbnail" Width="100" Height="100" HorizontalAlignment="Left" Margin="0 10 0 0"  />

            <Button Name="btnPickContact" Content="pick a contact" Click="btnPickContact_Click" Margin="0 10 0 0" />

            <Button Name="btnPickContacts" Content="pick multiple contacts" Click="btnPickContacts_Click" Margin="0 10 0 0" />

        </StackPanel>
    </Grid>
</Page>

Picker/ContactPickerDemo.xaml.cs

/*
 * 演示如何通过 ContactPicker 选择一个或多个联系人
 * 
 * ContactPicker - 联系人选择窗口
 *     CommitButtonText - 联系人选择窗口的确定按钮的显示文本,此按钮默认显示的文本为“确定”
 *     SelectionMode - 选取模式(ContactSelectionMode 枚举)
 *         Contacts - 请对我提供联系人的全部字段的数据,默认值
 *         Fields - 请对我提供指定字段的数据
 *     DesiredFields - 当 SelectionMode.Fields 时,请对我提供指定字段的数据,字段名称来自 KnownContactField 枚举
 *     PickSingleContactAsync() - 选取一个联系人,返回 ContactInformation 对象
 *     PickMultipleContactsAsync() - 选取多个联系人,返回 ContactInformation 对象集合
 *     
 * ContactInformation - 联系人信息对象
 *     Name, Emails, PhoneNumbers, Locations, InstantMessages, CustomFields
 *     GetThumbnailAsync() - 获取联系人缩略图
 */

using System;
using System.Collections.Generic;
using System.Linq;
using Windows.ApplicationModel.Contacts;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using XamlDemo.Common;

namespace XamlDemo.Picker
{
    public sealed partial class ContactPickerDemo : Page
    {
        public ContactPickerDemo()
        {
            this.InitializeComponent();
        }

        private async void btnPickContact_Click(object sender, RoutedEventArgs e)
        {
            if (Helper.EnsureUnsnapped())
            {
                ContactPicker contactPicker = new ContactPicker();
                contactPicker.CommitButtonText = "确定";
                contactPicker.SelectionMode = ContactSelectionMode.Contacts;

                // 启动联系人选取器,以选择一个联系人
                ContactInformation contact = await contactPicker.PickSingleContactAsync();

                if (contact != null)
                {
                    lblMsg.Text = "name: " + contact.Name;
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "emails: " + string.Join(",", contact.Emails.Select(p => new { email = p.Value }));
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "phoneNumbers: " + string.Join(",", contact.PhoneNumbers.Select(p => new { phoneNumber = p.Value }));

                    IRandomAccessStreamWithContentType stream = await contact.GetThumbnailAsync();
                    if (stream != null && stream.Size > 0)
                    {
                        BitmapImage bitmap = new BitmapImage();
                        bitmap.SetSource(stream);
                        imgThumbnail.Source = bitmap;
                    }
                }
                else
                {
                    lblMsg.Text = "取消了";
                }
            }
        }

        private async void btnPickContacts_Click(object sender, RoutedEventArgs e)
        {
            if (Helper.EnsureUnsnapped())
            {
                var contactPicker = new ContactPicker();

                // 启动联系人选取器,以选择多个联系人
                IReadOnlyList<ContactInformation> contacts = await contactPicker.PickMultipleContactsAsync();

                if (contacts != null && contacts.Count > 0)
                {
                    ContactInformation contact = contacts[0];

                    lblMsg.Text = "contacts count: " + contacts.Count.ToString();
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "first contact name: " + contact.Name;
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "first contact emails: " + string.Join(",", contact.Emails.Select(p => new { email = p.Value }));
                    lblMsg.Text += Environment.NewLine;
                    lblMsg.Text += "first contact phoneNumbers: " + string.Join(",", contact.PhoneNumbers.Select(p => new { phoneNumber = p.Value }));

                    IRandomAccessStreamWithContentType stream = await contact.GetThumbnailAsync();
                    if (stream != null && stream.Size > 0)
                    {
                        BitmapImage bitmap = new BitmapImage();
                        bitmap.SetSource(stream);
                        imgThumbnail.Source = bitmap;
                    }
                }
                else
                {
                    lblMsg.Text = "取消了";
                }
            }
        }
    }
}



OK
[源码下载]