id="info"

Microsoft

Use Contacts in Windows Phone 7 development

Learn how to use Contacts when developing WP7 apps, and read about two approaches for using the data from this class.

One item that is opened up to developers in the Mango update for Windows Phone 7 is the Contacts list. You cannot edit Contact data, but you can read it and use it within your application. It is easy to work with Contacts.

The Contacts class is under the Microsoft.Phone.UserData namespace, and getting a new instance of this class allows you to work with it. Unfortunately, we cannot use LINQ to directly access it; in fact, all you can really do with it is get a list of Accounts that contacts can be associated with, or query it asynchronously with the SearchAsync() method.

You will need to hook up an event handler to the SearchCompleted event to receive the data. From there, you can call the SearchAsync() method. SearchAsync() takes three parameters:

  • filter - The string of data for which you are searching.
  • filterKind - A value from the FilterKind enumeration to specify the location of the data for which you are looking. The possible values are DisplayName, EmailAddress, PhoneNumber, None, or PinnedToStart.
  • state - An object that will be passed back in the arguments to the event handler; this allows you to connect the event handler to the original search request, or pass data through to the event handler.

An interesting thing to note is that choosing a filterKind of PinnedToStart or None returns all of the Contacts on the Start menu or in the phone, respectively, regardless of what is entered for the filter argument. The full details of how items are found is on MSDN.

Once the search results are returned, the event handler gets an object of type ContactsSearchEventArgs. This arguments object contains the parameters as properties with the names of Filter, FilterKind, and State. It also has a Results property of type IEnumerable<Contact>. This means that you can take the Results and use LINQ on them to refine what you get out of it, or attach it directly to a UI binding.

Each individual Contact instance has the following useful properties and methods:

  • Accounts - an IEnumerable<Account> of which accounts the Contact has been linked to.
  • Addresses - an IEnumerable<ContactAddress> with the addresses for the Contact.
  • Companies - IEnumerable<ContactCompanyInformation> filled with the companies a Contact is connected to.
  • CompleteName - an instance of CompleteName, containing a granular breakdown of the Contact's name.
  • DisplayName - a string with the name that gets displayed to the phone's user.
  • EmailAddresses - an IEnumerable<ContactEmailAddress> that contains the email address and kind (like "personal" or "work").
  • GetPicture() - returns a stream of data for the Contact's picture.
  • PhoneNumbers - an IEnumerable<ContactPhoneNumber> with all of the phone numbers for the Contact. The phone numbers have a "Kind" property showing their purpose.

There are a number of additional properties and methods, but these are the most useful for the majority of applications.

In terms of using the data, there are two approaches. The first is to search as the user wants using SearchAsync() (Sample code A). The other way is to grab the data all at once (such as on app initialization) with a search of FilterKind.None, and then use LINQ to search when the user wants to look for something (Sample code B); this allows for much more fine-grained searches. Sample code A
private Contacts contactList = new Contacts();
public MainPage()

{

InitializeComponent();

contactList.SearchCompleted +=new EventHandler<ContactsSearchEventArgs>(contactList_SearchCompleted);

contactList.SearchAsync("Justin James", FilterKind.DisplayName, new object());

}
private void contactList_SearchCompleted(object sender, ContactsSearchEventArgs e)

{

var foundItem = e.Results.FirstOrDefault();

// Do something with the data

}
Sample code B
private Contacts contactList = new Contacts();
private IEnumerable<Contact> allContacts;
public MainPage()

{

InitializeComponent();

contactList.SearchCompleted +=new EventHandler<ContactsSearchEventArgs>(contactList_SearchCompleted);

contactList.SearchAsync(string.Empty, FilterKind.None, new object());

}
private void contactList_SearchCompleted(object sender, ContactsSearchEventArgs e)

{

allContacts = e.Results;

var justinJamesResults = from contact in allContacts

where contact.CompleteName.FirstName == "Justin" && contact.CompleteName.LastName == "James"

select contact;

// Do something with the data

}

I would probably stick with the LINQ version from Sample Code A, because with the "Fast Application Switching" it is possible for your app to be in memory for a very, very long time without re-initializing, and it would look bad if your application could not find a contact that the user just added.

J.Ja

About

Justin James is the Lead Architect for Conigent.

Editor's Picks