How to display the photo of a contact for Windows Phone 8
[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]
The process for displaying the photo of a contact is to get a reference to the Contact object, create a new bitmap image, set its source to GetPicture, and then display the bitmap in the user interface. You can also create a custom data converter and data-bind the photo to the user interface. For more information about accessing contact data, see How to access contact data for Windows Phone 8.
Note
Windows Phone SDK 7.1 gives you read-only access to the user’s contact data, aggregated across the user's different accounts. Most accounts provide access to photos. For more information, see Contacts and Calendar for Windows Phone 8.
This topic contains the following sections.
Displaying the photo of a contact
In this procedure, you put the code in a button click event for testing purposes only. In your own applications, you can access a contact photo wherever you need it. The following procedure assumes that you have a Windows Phone application that has a page that you can add controls to.
Important Note: |
---|
Windows Phone Emulator contains sample contacts; however, they do not have photos. You should test this procedure using a physical device. |
To display the photo of a contact
Open the XAML editor for your page and add the following code. You can add the code to the Content Panel or Layout Root GRID element. This creates a blank image control to hold the photo and a button. It also puts a theme-aware border around the photo.
<StackPanel Orientation="Horizontal"> <Border BorderThickness="2" HorizontalAlignment="Left" BorderBrush="{StaticResource PhoneAccentBrush}" > <Image Name="Picture" Height="85" Width="85" HorizontalAlignment="Left" /> </Border> <Button Content="Get One Picture" Width="Auto" Click="ButtonOnePicture_Click" /> </StackPanel>
Open the code-behind file for your page. At the top, add the following statements.
using Microsoft.Phone.UserData; using System.Windows.Media.Imaging;
Imports Microsoft.Phone.UserData imports System.Windows.Media.Imaging
Add the following code to the class for your page. This code contains the button click event, and starts the asynchronous contact search.
private void ButtonOnePicture_Click(object sender, RoutedEventArgs e) { Contacts cons = new Contacts(); //Identify the method that runs after the asynchronous search completes. cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted_One); //Start the asynchronous search. cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #2 Picture"); //cons.SearchAsync(String.Empty, FilterKind.PinnedToStart, "Contacts Test #2 Picture"); }
Private Sub ButtonOnePicture_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Dim cons As Contacts = New Contacts() 'Identify the method that runs after the asynchronous search completes. AddHandler cons.SearchCompleted, AddressOf Contacts_SearchCompleted_One 'Start the asynchronous search. cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #2 Picture") 'cons.SearchAsync(String.Empty, FilterKind.PinnedToStart, "Contacts Test #2 Picture") End Sub
Add the following code to the class for your page. This code contains the method to handle the completed event of the asynchronous search. In this code, you take the first contact returned by the search, create a new bitmap image, set its source to GetPicture, and display the photo in the image control that you added in step 1.
void Contacts_SearchCompleted_One(object sender, ContactsSearchEventArgs e) { try { //We are using the first contact only. Contact con = e.Results.First(); BitmapImage img = new BitmapImage(); img.SetSource(con.GetPicture()); Picture.Source = img; } catch (Exception) { //We can't get a picture of the contact. } }
Private Sub Contacts_SearchCompleted_One(sender As Object, e As ContactsSearchEventArgs) Try 'We are using the first contact only. Dim con As Contact = e.Results.First() Dim img As BitmapImage = new BitmapImage() img.SetSource(con.GetPicture()) Picture.Source = img Catch ex As System.Exception 'We can't get a picture of the contact. End Try End Sub
Save and build your solution.
Start your application and click the button.
The photo of the first contact should appear. If the photo does not appear, it may be because the first contact does not have a photo. Try changing the contact search to return the contacts pinned to the Start screen instead of all contacts. To do that, in the code for step 3, uncomment the last line and comment out the second-to-last line. For more information, see Contact filtering and matching for Windows Phone 8.
Data-binding photos to the user interface
Because contact photos are not properties, but instead are retrieved by calling the GetPicture method, you need a custom data converter to bind them. In this procedure, you put the code in a button click event for testing purposes only. In your own applications, you can access contact photos wherever you need them. The following procedure assumes that you have a Windows Phone application that has a page that you can add controls to.
Important Note: |
---|
Windows Phone Emulator contains sample contacts; however, they do not have photos. You should test this procedure using a physical device. |
To data-bind a photo to the user interface
Open the code-behind file for your page. At the top, add the following statements.
using Microsoft.Phone.UserData; using System.Windows.Media.Imaging;
Imports Microsoft.Phone.UserData imports System.Windows.Media.Imaging
Add the following code to the class for your page. This code contains the button click event, and starts the asynchronous contact search.
private void ButtonManyPictures_Click(object sender, RoutedEventArgs e) { Contacts cons = new Contacts(); //Identify the method that runs after the asynchronous search completes. cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted_Many); //Start the asynchronous search. cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #3 Picture"); }
Private Sub ButtonManyPictures_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Dim cons As Contacts = New Contacts() 'Identify the method that runs after the asynchronous search completes. AddHandler cons.SearchCompleted, AddressOf Contacts_SearchCompleted_Many 'Start the asynchronous search cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #3 Picture") End Sub
Add the following code to the class for your page. This code contains the method to handle the completed event of the asynchronous search. In this code, you bind the contact data, including the photo, by setting the data context of the list box from step 1 equal to the results of the search.
void Contacts_SearchCompleted_Many(object sender, ContactsSearchEventArgs e) { try { //Bind the results to the list box that displays them in the UI. ContactResultsData.DataContext = e.Results; } catch (System.Exception) { //No results } }
Private Sub Contacts_SearchCompleted_Many(sender As Object, e As ContactsSearchEventArgs) Try 'Bind the results to the user interface. ContactResultsData.DataContext = e.Results Catch ex As System.Exception 'No results End Try End Sub
Add the following code. The code should go inside the namespace, but after the Page class. This is the custom data converter that enables you to bind the photo to the user interface.
public class ContactPictureConverter : System.Windows.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Contact c = value as Contact; if (c == null) return null; System.IO.Stream imageStream = c.GetPicture(); if (null != imageStream) { return Microsoft.Phone.PictureDecoder.DecodeJpeg(imageStream); } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
Public Class ContactPictureConverter Implements System.Windows.Data.IValueConverter Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object _ Implements System.Windows.Data.IValueConverter.Convert Dim c as Contact = CType(value, Contact) If c Is Nothing Then Return Nothing End If Dim imageStream as System.IO.Stream = c.GetPicture() If imageStream IsNot Nothing Then Return Microsoft.Phone.PictureDecoder.DecodeJpeg(imageStream) End If Return Nothing End Function Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object _ Implements System.Windows.Data.IValueConverter.ConvertBack throw new NotImplementedException() End Function End Class
Open the XAML editor for your page. In the <phone:PhoneApplicationPage> tag, with the other namespace declarations, add the following code. Replace the placeholder YOURSOLUTIONNAME with the name of your solution, without the file extension. This allows you to access the custom data converter.
xmlns:MyApp="clr-namespace:YOURSOLUTIONNAME"
After the PHONE:PHONEAPPLICATIONPAGE element and before the GRID element, add the following code. This enables you to use the custom data converter in the data binding.
<phone:PhoneApplicationPage.Resources> <MyApp:ContactPictureConverter x:Key="ContactPictureConverter" /> </phone:PhoneApplicationPage.Resources>
Add the following code. You can add the code to the Content Panel or Layout Root GRID element.
<StackPanel Orientation="Vertical"> <Button Content="Get Many Pictures" Width="Auto" Click="ButtonManyPictures_Click" /> <ListBox Grid.Row="1" Name="ContactResultsData" ItemsSource="{Binding}" Height="300" Margin="24,24,0,0" VerticalAlignment="Top"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Border BorderThickness="2" HorizontalAlignment="Left" BorderBrush="{StaticResource PhoneAccentBrush}" > <Image Source="{Binding Converter={StaticResource ContactPictureConverter}}" Width="48" Height="48" Stretch="Fill" /> </Border> <TextBlock Name="ContactResults" Text="{Binding Path=DisplayName, Mode=OneWay}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel>
This XAML creates a button and a list box that you bind to the contact data. The data template for each row of the list box contains the photo and the name of the contact. For more information, see Data binding for Windows Phone 8 and Data Templating Overview.
Save and build your solution.
Start your application and click the button.
The contacts fill the list box. Scroll until you see a contact that has a photo.
See Also
Reference
Other Resources
Walkthrough: Accessing contact and calendar data for Windows Phone 8