Building a Windows Phone Application that Accesses Contacts

Introduction

Windows Phone provides developers the programmatic ability to access contacts that enables them to build experiences that integrate tightly with the native contacts experience.

The Windows Phone platform supports integration with contacts in two ways:

1. It supports read-only access to the phone’s contacts store. This support is available in all versions of Windows Phone operating systems.

2. It supports creation of a custom contact store associated with an application. This is only supported in Windows Phone 8 and allows adding, reading, updating and deleting contacts in the custom contact store. There is also API support to sync the custom contacts to a remote storage location in the cloud for backup purposes.

Contacts Basics

Windows Phone supports access to contacts from the following data sources:

  • Windows Phone device
  • Windows Live Social
  • Exchange accounts
  • Mobile operate address book
  • Facebook
  • Contacts in the custom contacts store

Access to contacts is enabled by using the Contacts class in the Microsoft.Phone.UserData namespace.

The Contacts class has the SearchCompleted event, which is fired when a search for contacts completes.

To have access to contacts, the Windows Phone application will need to declare the capability ID_CAP_CONTACTS in the application manifest file WMAppManifest.xml.

The Contacts.SearchAsync API is used to search for a specific contact by providing a filter. The ContactsSearchEventArgs object is returned as part of the SearchCompleted delegate.

Hands On

We will build a simple application that searches for contacts with a specified first name or email address.

For this hands on, we will use Visual Studio 2013 and build a Windows Phone 8 application.

Create a new Visual Studio Windows Phone project titled WPContactDemo.

New Project
New Project

Under the Solution Explorer, expand Properties and double-click  WMAppManifest.xml.

Double-click  WMAppManifest.xml
Double-click  WMAppManifest.xml

Click on Capabilities and select ID_CAP_CONTACTS to declare the application’s capability to access contacts.

Select ID_CAP_CONTACTS
Select ID_CAP_CONTACTS

Next, we will add a few TextBox controls and a Button control to MainPage.xaml as shown below.

Add TextBox controls and a Button control
Add TextBox controls and a Button control

In our application, we will search for contacts by one of the following: First name, Last Name or Email address. We will also add a ListBox control below the search button to display our results.

Our XAML for the mainpage is below (added sections are highlighted).

<phone:PhoneApplicationPage
    x:Class="WPContactDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!-- LOCALIZATION NOTE:
            To localize the displayed strings copy their values to appropriately named
            keys in the app's neutral language resource file (AppResources.resx) then
            replace the hard-coded text value between the attributes' quotation marks
            with the binding clause whose path points to that string name.
 
            For example:
 
                Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"
 
            This binding points to the template's string resource named "ApplicationTitle".
 
            Adding supported languages in the Project Properties tab will create a
            new resx file per language that can carry the translated values of your
            UI strings. The binding in these examples will cause the value of the
            attributes to be drawn from the .resx file that matches the
            CurrentUICulture of the app at run time.
         -->
 
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox x:Name="textBoxFirstName" HorizontalAlignment="Left" Height="72" Margin="178,25,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="268"/>
            <TextBlock HorizontalAlignment="Left" Margin="60,50,0,0" TextWrapping="Wrap" Text="First Name" VerticalAlignment="Top"/>
            <TextBox x:Name="textBoxEmailAddress" HorizontalAlignment="Left" Height="72" Margin="178,147,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="268"/>
            <TextBlock HorizontalAlignment="Left" Margin="34,172,0,0" TextWrapping="Wrap" Text="Email address" VerticalAlignment="Top"/>
            <Button x:Name="buttonSearchContacts" Content="Search" HorizontalAlignment="Left" Margin="216,258,0,0" VerticalAlignment="Top" Click="buttonSearchContacts_Click"/>
            <ListBox x:Name="listContacts" ItemsSource="{Binding}"  HorizontalAlignment="Left" Height="224" Margin="60,340,0,0" VerticalAlignment="Top" Width="348">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" >
                            <TextBlock Name="ContactResults" Text="{Binding Path=DisplayName, Mode=OneWay}" FontSize="{StaticResource PhoneFontSizeExtraLarge}" Margin="18,8,0,0" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
 
        </Grid>
 
        <!--Uncomment to see an alignment grid to help ensure your controls are
            aligned on common boundaries.  The image has a top margin of -32px to
            account for the System Tray. Set this to 0 (or remove the margin altogether)
            if the System Tray is hidden.
 
            Before shipping remove this XAML and the image itself.-->
        <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->
    </Grid>
 
</phone:PhoneApplicationPage>

If you observe closely, you will notice that for the listbox, we have a template associated with displaying the “Display name” of the contact in the results.

To search on an input, we will wire up the Search button’s click event with code that will parse the search criteria and invoke the Contacts.SearchAsync API.

In the click event, we will create an instance of the Contacts store, and register an event handler for the search completion event. We will also invoke the search APIs depending on whether the search is by Display name or email address.

private void buttonSearchContacts_Click(object sender, RoutedEventArgs e)
        {
            Contacts contactStore = new Contacts();
            contactStore.SearchCompleted += contactStore_SearchCompleted;
            if (textBoxFirstName.Text != "")
                contactStore.SearchAsync(textBoxFirstName.Text, FilterKind.DisplayName, "Searching by first name");
            if (textBoxEmailAddress.Text != "")
                contactStore.SearchAsync(textBoxEmailAddress.Text, FilterKind.EmailAddress, "Searching by email address");
 
        }

Finally, we will implement the event handler for the Search completion event.

Here, we will set the data context of the ListBox control to the Results property of ContactsSearchEventArgs object.

void contactStore_SearchCompleted(object sender, ContactsSearchEventArgs e)
        {
            MessageBox.Show(e.State.ToString());
            listContacts.DataContext = e.Results;
        }

Our application is now ready. You can now run the application to test search your contacts by Display name or email address. The sample code for the demo is available below.

Summary

In this article, we learned a few basics about accessing Contacts on a Windows Phone. I hope you have found this article useful.

About the Author

Vipul Patel is a Program Manager currently working at Amazon Corporation. He has formerly worked at Microsoft in the Lync team and in the .NET team (in the Base Class libraries and the Debugging and Profiling team). He can be reached at vipul.patel@hotmail.com

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read