Si quieres probar la aplicación que cubre a este artículo en tu dispositivo, puedes descargarla desde el Windows Phone Marketplace.
Hoy vamos a hablar acerca de un nuevo espacio de nombres disponible en Windows Phone: Microsoft.Phone.UserData. En la serie original 31 días de Windows Phone, cubrí un tema en el día 8: Choosers. Con esas tareas, éramos capaces de permitir al usuario elegir un registro de una su lista de contactos del teléfono y obtener una información específica de ese contacto, una dirección de correo o un número telefónico, pero no ambos al mismo tiempo.
Con este nuevo namespace en Windows Phone 7.5, tenemos ahora la habilidad de tratar a la lista de contactos del usuario como una base de datos local. Podremos buscar, obtener múltiples contactos y obtener sus registros enteros. Es mucho mas robusto , pero trabajar con esto es mucho mas manual.
Como nota, así como el tío de Peter Parker, el tío Ben, mencionó, “con un gran poder, viene una gran responsabilidad”. Solo porque tienes acceso a la lista de contactos del usuario, no quiere decir que tu explotes ese privilegio. Obtener una aplicación instalada en el teléfono del usuario requiere un alto nivel de confianza. Si tu violas esa confianza por ejemplo enviando Spam a todos sus amigos y contactos con un email y demás basura, no solo serás desinstalado, sino que la frustración del usuario puede verse reflejada en comentarios negativos en el marketplace.
Finalmente, es importante recordar que la información a la que estamos accediendo es de SOLO LECTURA. No podemos hacer actualizaciones, borrar nada o incluso agregar nada. Este es un mecanismo simple para encontrar alguno o todos los contactos en el teléfono y usar los datos dentro de nuestras aplicaciones.
Crear la interfaz del usuario
Como todos los artículos de esta seria, primero debemos comenzar con la interfaz del usuario. En este ejemplo, estamos usando la plantilla preestablecida de Windows Phone y he agregado un ListBox con algunos elementos enlazados que estaremos usando después. Para mayor información en la parte de enlazado de datos puedes checar el Día 13 de los 31 días de Silverlight. También he agregado un TextBox que será usado para buscar a través de los contactos.
Aquí está el XAML que estaremos usando para esta aplicación:
<phone:PhoneApplicationPage
x:Class=”Dia_8_Contactos.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” d:DesignWidth=”480″ d:DesignHeight=”768″
FontFamily=”{StaticResource PhoneFontFamilyNormal}”
FontSize=”{StaticResource PhoneFontSizeNormal}”
Foreground=”{StaticResource PhoneForegroundBrush}”
SupportedOrientations=”Portrait” Orientation=”Portrait”
shell:SystemTray.IsVisible=”True”>
<Grid x:Name=”LayoutRoot” Background=”Transparent”>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>
<StackPanel x:Name=”TitlePanel” Grid.Row=”0″ Margin=”12,17,0,28″>
<TextBlock x:Name=”ApplicationTitle” Text=”LA LIGA SILVERLIGHT” Style=”{StaticResource PhoneTextNormalStyle}”/>
<TextBlock x:Name=”PageTitle” Text=”contactos” Margin=”9,-7,0,0″ Style=”{StaticResource PhoneTextTitle1Style}”/>
</StackPanel>
<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>
<TextBox x:Name=”txtContactos” Height=”80″ Margin=”0,-12,0,539″ TextChanged=”txtContactos_TextChanged”/>
<ListBox x:Name=”lstContactos” Margin=”0,70,0,0″>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text=”{Binding Path=DisplayName, Mode=OneWay}” />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
Las partes específicas que resaltar en este XAML es nuestro ListBox, llamado lstContactos, y el TextBlock dentro de su DataTemplate. Hemos enlazado este TextBlock al valor DisplayName, el cual es el que va a estar alimentándose de nuestra lista de contactos. La otra pieza importante es el TextBox llamado txtContactos. Usaremos el contenido de esa caja como nuestro criterio de búsqueda implementando el manejador de eventos TextChanged. Así es como nuestra interfaz final quedará.
Buscando por información de contacto
En nuestro código C#, necesitamos asegurarnos que tenemos una sentencia using para el nombre de espacio Microsoft.Phone.UserData. Esto es lo que nos permitirá tener acceso a la información de contacto en el dispositivo.
El primer paso es capturar cualquier cambio de texto de nuestro TextBox. Hemos definido esto con un manejador de eventos en nuestro XAML, pero necesitamos crear el método de ese manejador. Aquí está el código inicial, con el manejador de eventos creado.
using System;
using System.Linq;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;
using System.Collections.Generic;
namespace Dia_8_Contactos
{
public partial class MainPage : PhoneApplicationPage
{
Contacts contactos = new Contacts();
public MainPage()
{
InitializeComponent();
contactos.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contactos_SearchCompleted);
BuscarContactos(String.Empty);
}
private void txtContactos_TextChanged(object sender, TextChangedEventArgs e)
{
//COMENZAR LA BÚSQUEDA
}
}
}
Como puedes ver, el evento txtContactos_TextChanged se dispara cada vez que el valor de nuestro TextBox cambia y lo he hecho para llamar a un método separado, BuscarContactos, para ejecutar la búsqueda. BuscarContactos toma una cadena como parámetro y usaremos este valor en nuestro código de búsqueda.
Para poder buscar en la información, sin embargo, necesitamos crear una nueva instancia del objeto de tipo Contacts. (Esta es la razón por la que utilizamos el nombre de espacio de Microsoft.Phone.UserData) Para obtener esta información, necesitamos ajustar la búsqueda asíncrona contra la lista de contactos. El objeto Contacts tiene un manejador de eventos, SearchCompleted, que será el que usaremos para obtener los resultados de nuestra búsqueda cuando esté completada. Finalmente, usaremos el método SearchAsync() para ejecutar la búsqueda con criterios específicos. Vamos a darle un vistazo a nuestro C# final y después pasaré un poco más hablando acerca de los diferentes parámetros que podemos utilizar.
using System;
using System.Linq;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;
using System.Collections.Generic;
namespace Dia_8_Contactos
{
public partial class MainPage : PhoneApplicationPage
{
Contacts contactos = new Contacts();
public MainPage()
{
InitializeComponent();
contactos.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contactos_SearchCompleted);
BuscarContactos(String.Empty);
}
private void txtContactos_TextChanged(object sender, TextChangedEventArgs e)
{
BuscarContactos(txtContactos.Text);
}
void contactos_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
lstContactos.ItemsSource = e.Results;
}
private void BuscarContactos(string terminoBuscar)
{
contactos.SearchAsync(terminoBuscar, FilterKind.DisplayName, null);
}
}
}
Como puedes ver en nuestro método constructor, podemos llamar al método BuscarContactos que creamos antes, pasando en String.Empty, al usar una cadena vacía, le indicamos al método SearchAsync() que queremos TODOS los contactos de la lista. Mientras uses esto en el emulador (solo tiene 7 contactos predeterminados) responderá de manera correcta, un teléfono puede tener miles de registros y podría tomar unos cuantos segundos en cargar. Ten esto en mente mientras uses la funcinoalidad y considera usar una ProgressBar u otro mecanismo para dejarle saber al usuario que estás obteniendo información.
Si miras a la firma del método Contacts.SearchAsync, este tomará tres parámetros:
string – Este es el criterio de búsqueda que estarás usando. En nuestro ejemplo, es el contenido del TextBox que creamos en nuestro XAML.
FilterKind – Esto te permitirá buscar no solo por número de teléfono, nombre desplegado o dirección de correo. Si seleccionas None, tu criterio de búsqueda será ignorado.
object – Este es un parámetro de tipo objeto que puedes usar para pasar información en la búsqueda así cuando recibes los resultados, sabrás algo acerca de lo que estás tratando de buscar. Este puede ser tan simple como un identificador de cadena hasta un objeto específico que podrás necesitar después.
Si corres tu aplicación ahora, podrías ver que cuando escribas en el TextBox filtrará los resultados en tu ListBox. Aquí un vistazo de como se vería una lista filtrada en el emulador de Windows Phone.
Mirar a la información obtenida
Listo, hemos exitosamente consultado a los contactos en el dispositivo, y enlazado a la ListBox. Lo que no hemos visto, es que tipos de información podemos obtener, aquí es abundante. También debido a que recibimos una colección de tipo IEnumerable, podremos usar LINQ para consultar nuestros resultados.
Estoy modificando el método contactos_SearchCompleted de nuestro ejemplo arriba, agrupando el primer registro de la información y solo almacenando algunos de los valores en variables locales para demostración. Podría ser mas fácil mostrar esta información en la pantalla o guardar los valores en variables locales para demostración. Podrías mostrar la información en la pantalla o guardarla en el mecanismo de almacenamiento de tu aplicación. Aquí es como se verá el método con algunas de las propiedades del objeto de tipo Contact expuesto para ti.
void contactos_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
lstContactos.ItemsSource = e.Results;
Contact resultadoContacto = e.Results.FirstOrDefault();
string firstname = resultadoContacto.CompleteName.FirstName;
string lastname = resultadoContacto.CompleteName.LastName;
string emailaddress = resultadoContacto.EmailAddresses.FirstOrDefault().EmailAddress;
string phonenumber = resultadoContacto.PhoneNumbers.FirstOrDefault().PhoneNumber;
bool isPinnedToStart = resultadoContacto.IsPinnedToStart;
}
El ejemplo arriba es solo una muestra pequeña muestra de la información disponible en un registro de contactos y dependiendo de tus necesidades, todo lo demás está ahí. Aquí hay un ejemplo sencillo de lo que puedes hacer (asumiendo que esté disponible en el registro de contactos).
Accounts- La lista de cuentas con las que esté asociado. Esto incluye cosas como Facebook, Windows live, Outlook, etc.
Addresses– La lista de direcciones para este contacto. Cada dirección también incluye la “cuenta” (de arriba) con la que esté asociada, el “tipo” de dirección (como trabajo, casa etc) y finalmente PhysicalAddress, los cuales exponen todos los valores esperados como dirección1, ciudad, estadoProvincia y País/Región.
Birthdays – No estoy seguro de porque un usuario tendría diferentes cumpleaños pero cada cuenta puede tener diferentes valores, así podrás tener una lista. También, si un año no está especificado, obtendrás un valor de “1” para en año en esos casos.
Children – Una lista simple de cadenas que representan los nombres de los hijos de los contactos.
Companies – De nuevo enriquecidas con la información del contacto
CompleteName – Mostrado en nuestro código de ejemplo arriba, este contiene todas las propiedades de un nombre de contacto incluyendo título, sufijo, nombre intermedio, etc.
DisplayName – Una simple cadena que representa el nombre que es utilizado en el teléfono para este contacto.
EmailAddresses – Una lista de las direcciones de correo electrónico, con “cuenta” y “tipo” de información también.
IsPinnedToStart – Esta es una pieza booleana interesante, porque generalmente indica cuales usuarios son los mas importantes para ellos (porque el contacto está anclado a la pantalla de inicio del usuario).
Notes - Una lista de cadenas que el usuario a guardado como notas acerca de este contacto.
PhoneNumbers – Una lista de todos los números de teléfono asociados con un contacto, también esta decorado con “cuenta” y “tipo” de información.
SignificantOthers – Quizá pienses que solo hay un valor para este también, pero, tu sabes. De cualquier forma, es similar a la propiedad Children. Una lista de cadenas.
Finalmente, me quiero asegurar que tengas una forma visual para lo que hace esta aplicación, así que aquí hay un video mostrando la aplicación que recién creamos.
En resumen
Yo pienso que es un buen inicio para usar la API de contactos en un Windows Phone. Este nombre de espacio entero esta solo disponible en teléfonos corriendo el SO Windows Phone 7.5, así que si estás trabajando en una aplicación 7.0, no serás capaz de usarla (Pero realmente ¿para que seguirías creando una aplicación 7.0? ¡Es hora de actualizarse!).
Para descargar una solución Windows Phone que utilice todo el código de este artículo, puedes hacerlo.
Puedes descargar el código aquí.
Mañana, vamos a hablar acerca de el otro lado del nombre de espacios UserData, el API del calendario. Es otro conjunto de información de solo lectura, pero no permite tener visibilidad dentro de la disponibilidad del usuario en cierto periodo de tiempo. Nos vemos.
