L'SDK di Windows Phone consente l'accesso in sola lettura allo storage dei contatti e dei dati del calendario. È importante ricordare che tali dati, anche se dal punto di vista della user experience sono centralizzati e uniformi, in realtà posso provenire da diversi fonti: semplice inserimento manuale, siti di social networking o altri fornitori di dati.
Non tutti i dati però sono esposti tramite le API, in base all'enumerator StorageKind saremo in grado di capire la provenienza di un dato e di conseguenza sapere quali informazioni potremmo consultare. La seguente tabella riassume i dati disponibili per ogni fornitore:
Fornitore | Nome del contatto | Foto del contatto | Altri dati del contatto | Appuntamenti nel calendario | StorageKind |
---|---|---|---|---|---|
Device Windows Phone | Sì | Sì | Sì | Sì | Phone |
Windows Live Social | Sì | Sì | Sì | Sì | WindowsLive |
Windows Live Rolodex | Sì | Sì | Sì | Sì | WindowsLive |
Account di Exchange (contatti provenienti dall'address book locale, non dall'address book globale) | Sì | Sì | Sì | Sì | Outlook |
Address Book dell'operatore mobile | Sì | Sì | Sì | No | Other |
Sì | Sì | No | No | ||
Aggregated Network di Windows Live (Twitter, LinkedIn ecc.ecc.) | No | No | No | No | None |
Contatti
Il processo per accedere ai dati dei contatti prevede:
- la creazione di un'instanza dell'oggetto
Contacts
- una ricerca asincrona
- l'elaborazione dei risultati, instanze della classe
Contact
Per provare il seguente codice basta creare una semplice Windows Phone Application e inserire un button che userà questo event handler di click:
private void button1_Click(object sender, RoutedEventArgs e)
{
Contacts contatti = new Contacts();
contatti.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
contatti.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #1");
}
void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
MessageBox.Show(e.Results.Count().ToString());
}
Merita una nota il metodo SearchAsync, la sua firma prevede come primo parametro il filtro da utilizzare per ricercare i contatti, il secondo parametro è un enumerator che rappresenta il tipo di filtro, mentre l'ultimo è un classico user state per inserire informazioni da rileggere nella callback SearchCompleted
.
Se il tipo di filtro è EmailAddress
, PhoneNumber
o DisplayName
il filtro deve contenere l'ovvia stringa di ricerca mentre il primo parametro verrà ignorato se il tipo di filtro è None
o PinnedToStart
.
È possibile inoltre usare LINQ per lavorare con i contatti del device, è importante però segnalare che le performance saranno nettamenti inferiori rispetto alle ricerche built-in che sono pre-indicizzate, specialmente se lavoreremo con dati di notevole dimensione.
Nel prossimo esempio usiamo una listbox di Silverlight per visualizzare i dati dei risultati della ricerca, tale elemento oltre alle proprietà di layout conterrà la definizione grafica del singolo elemento (ItemTemplate
), si noti l'espressione di binding per recuperare l'indirizzo email del contatto.
<ListBox Name="ContactResultsDataLINQ" ItemsSource="{Binding}" Height="200" Margin="24,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=EmailAddresses[0].EmailAddress, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Conclude l'esempio una query LINQ per filtrare gli indirizzi email che contengono la stringa "example":
void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
try
{
ContactResultsDataLINQ.DataContext =
from Contact con in e.Results
from ContactEmailAddress a in con.EmailAddresses
where a.EmailAddress.Contains("example")
select con;
}
catch (System.Exception)
{
//Nessun risultato
}
}
Appuntamenti
Il processo per accedere ai dati del calendario prevede la creazione di un'instanza dell'oggetto Appointments, una ricerca asincrona e un'elaborazione dei resultati, instanze della classe Appointment
.
Sono chiare le analogie con le API dei contatti, proviamo a scrivere un semplice esempio in grado di ricercare i primi 20 appuntamenti della prossima settimana.
private void button1_Click(object sender, RoutedEventArgs e)
{
Appointments appuntamenti = new Appointments();
appuntamenti.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(Appointments_SearchCompleted);
DateTime start = DateTime.Now;
DateTime end = start.AddDays(7);
int max = 20;
appuntamenti.SearchAsync(start, end, max, "Appointments Test #1");
}
void Appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
{
MessageBox.Show(e.Results.Count().ToString());
}
Il metodo SearchAsync in questo overload prevede il passaggio di un intervallo di date (il primo e il secondo parametro), un numero massimo di elementi restituiti e un classico user state che potremmo rileggere nella callback SearchCompleted.
Possiamo arricchire il precedente esempio con del codice XAML di user interface:
<ListBox Name="AppointmentResultsDataLINQ" ItemsSource="{Binding}" Height="200" Margin="24,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Subject, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Conclude l'esempio una query LINQ per filtrare gli appuntamenti che non sono "a giornata intera":
void Appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
{
try
{
AppointmentResultsDataLINQ.DataContext =
from Appointment appt in e.Results
where appt.IsAllDayEvent == false
select appt;
}
catch (System.Exception)
{
//Nessun risultato
}
}