Quando l'utente seleziona nella Charms Bar l'applicazione target per condividere un determinato contenuto, l'handler del relativo evento, rappresentato dal metodo OnShareTargetActivated, provvede a istanziare la pagina di visualizzazione del contenuto proveniente dall'applicazione source (nel nostro caso, ShareTargetPage1
) e a invocarne il metodo Activate, passando come parametro (di tipo ShareTargetActivatedEventArgs) i dati provenienti dall'applicazione source. Ecco il codice, invero piuttosto semplice, del metodo in questione:
/// <summary>
/// Invoked when the application is activated as the target of a sharing operation.
/// </summary>
/// <param name="args">Details about the activation request.</param>
protected override void OnShareTargetActivated(Windows.ApplicationModel.Activation.ShareTargetActivatedEventArgs args)
{
var shareTargetPage = new Html.it.Demo.SharingTarget.ShareTargetPage1();
shareTargetPage.Activate(args);
}
Il code behind di default della pagina ShareTargetPage1
consiste essenzialmente di due metodi:
Metodo | Descrizione |
---|---|
Activate | che si occupa di recuperare il contenuto condiviso dall'utente tramite l'applicazione source |
ShareButton_Click | che intercetta il click l'utente sul charm di Share per dare avvio alla vera e propria operazione di condivisione (ad esempio, pubblicando il contenuto su un social network, piuttosto che inviandolo per mail ai nostri contatti, e così via) |
Vediamo adesso di approfondire meglio i meccanismi attraverso i quali il contenuto condiviso dall'utente viene passato all'applicazione target (e, più precisamente, al metodo Activate
della pagina ShareTargetPage1
).
A questo proposito, si noti come la proprietà ShareOperation (che troviamo nel prossimo listato) della classe ShareTargetActivatedEventArgs
esponga a sua volta una proprietà di tipo DataPackageView
denominata Data. Quest'ultima classe contiene al suo interno, oltre a una serie di metodi per il recupero asincrono di specifiche tipologie di contenuto (come GetTextAsync
per il testo, GetHtmlFormatAsync
per contenuti HTML, etc.), anche una proprietà Properties
(anch'essa nel listato), di tipo DataPackagePropertySetView
, che permette di accedere alla collezione di oggetti provenienti dall'applicazione source, nonché a una serie predefinita di proprietà - come FileTypes
, Size
, Thumbnail
, Title
e Description
(alcune delle quali già viste nell'articolo dedicato alle applicazioni source) - che l'applicazione target può sfruttare per "conoscere" meglio il contenuto proveniente dall'applicazione source.
Il contenuto condiviso dall'utente sarà poi mostrato nella pagina XAML utilizzando il classico DefaultViewModel
che abbiamo già incontrato parlando del contratto di Search.
Ecco come appare il codice inserito di default da Visual Studio 2012 nella pagina SharingTargetPage1.xaml.cs
:
/// <summary>
/// Invoked when another application wants to share content through this application.
/// </summary>
/// <param name="args">Activation data used to coordinate the process with Windows.</param>
public async void Activate(ShareTargetActivatedEventArgs args)
{
this._shareOperation = args.ShareOperation;
// Communicate metadata about the shared content through the view model
var shareProperties = this._shareOperation.Data.Properties;
var thumbnailImage = new BitmapImage();
this.DefaultViewModel["Title"] = shareProperties.Title;
this.DefaultViewModel["Description"] = shareProperties.Description;
this.DefaultViewModel["Image"] = thumbnailImage;
this.DefaultViewModel["Sharing"] = false;
this.DefaultViewModel["ShowImage"] = false;
this.DefaultViewModel["Comment"] = String.Empty;
this.DefaultViewModel["SupportsComment"] = true;
Window.Current.Content = this;
Window.Current.Activate();
// Update the shared content's thumbnail image in the background
if (shareProperties.Thumbnail != null)
{
var stream = await shareProperties.Thumbnail.OpenReadAsync();
thumbnailImage.SetSource(stream);
this.DefaultViewModel["ShowImage"] = true;
}
}
Ora che la nostra pagina XAML è pronta a mostrare il testo proveniente dall'applicazione source, possiamo recuperarlo dal DataPackageView in modalità asincrona sfruttando il metodo GetTextAsync, non prima però di esserci assicurati che il contenuto proveniente dalla prima contenga effettivamente del testo. Il codice da aggiungere è evidenziato in grassetto nel seguente listato:
public async void Activate(ShareTargetActivatedEventArgs args)
{
this._shareOperation = args.ShareOperation;
// Communicate metadata about the shared content through the view model
var shareProperties = this._shareOperation.Data.Properties;
if (this._shareOperation.Data.AvailableFormats.Contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.Text))
{
this.DefaultViewModel["Content"] = await this._shareOperation.Data.GetTextAsync();
}
var thumbnailImage = new BitmapImage();
this.DefaultViewModel["Title"] = shareProperties.Title;
this.DefaultViewModel["Description"] = shareProperties.Description;
this.DefaultViewModel["Image"] = thumbnailImage;
this.DefaultViewModel["Sharing"] = false;
this.DefaultViewModel["ShowImage"] = false;
this.DefaultViewModel["Comment"] = String.Empty;
this.DefaultViewModel["SupportsComment"] = true;
Window.Current.Content = this;
Window.Current.Activate();
// Update the shared content's thumbnail image in the background
if (shareProperties.Thumbnail != null)
{
var stream = await shareProperties.Thumbnail.OpenReadAsync();
thumbnailImage.SetSource(stream);
this.DefaultViewModel["ShowImage"] = true;
}
}
L'altro metodo della pagina ShareTargetPage1
da considerare è l'handler del click sul pulsante di share, rappresentato dal metodo ShareButton_Click
. Sebbene l'implementazione di una qualche logica di business per la condivisione dei dati provenienti dall'applicazione source ecceda gli ambiti di questo articolo, l'implementazione di default dell'handler, riportata qui di seguito, merita un qualche commento:
/// <summary>
/// Invoked when the user clicks the Share button.
/// </summary>
/// <param name="sender">Instance of Button used to initiate sharing.</param>
/// <param name="e">Event data describing how the button was clicked.</param>
private void ShareButton_Click(object sender, RoutedEventArgs e)
{
this.DefaultViewModel["Sharing"] = true;
this._shareOperation.ReportStarted();
// TODO: Perform work appropriate to your sharing scenario using
// this._shareOperation.Data, typically with additional information captured
// through custom user interface elements added to this page such as
// this.DefaultViewModel["Comment"]
this._shareOperation.ReportCompleted();
}
Per quanto nel nostro esempio ci siamo limitati a condividere del semplice testo tra due applicazioni, niente vieta che a essere condivisi siano file di grandi dimensioni, o addirittura intere collezioni di foto, video e musica.
In questi casi, il processo di condivisione (incluso quello di comunicazione ed elaborazione dell'oggetto DataPackage
contenente le informazioni provenienti dall'applicazione source) può richiedere del tempo.
È chiaro che in queste situazioni (definite extended shares) sarebbe scorretto costringere l'utente a rimanere fermo sulla nostra applicazione in attesa che si completi il (più o meno lungo) processo di condivisione. È anzi probabile che, durante questa attesa, l'utente passi a un'altra applicazione o torni al menu Start, mettendo così la nostra applicazione in background.
Le due chiamate ReportStarted e ReportCompleted servono a far conoscere al sistema operativo che la nostra applicazione ha, rispettivamente, iniziato o completato il processo di condivisione, così da poter meglio gestire la sospensione o la chiusura dell'applicazione stessa .
Se adesso effettuiamo un nuovo deployment dell'applicazione e apriamo nuovamente Internet Explorer attivando la condivisione di un qualunque testo, l'applicazione target dovrebbe adesso comparire nell'elenco delle applicazioni in grado di condividere quel determinato tipo di contenuto. Il risultato è mostrato nella prossima immagine:
In conclusione, possiamo dire che l'implementazione del contratto nell'applicazione Target (a prescindere dalle eventuali complicazioni discendenti dalla logica di business e dalla presentazione dei contenuti, che possono risultare anche molto complessi) è relativamente semplice, grazie alle operazioni di "impacchettamento" delle informazioni condivise compiute da WinRT (Windows Runtime). L'unica cosa che rimane allo sviluppatore è accedere in modalità asincrona alle informazioni contenute nell'oggetto DataPackageView tramite i vari metodi messi a disposizione dall'infrastruttura e processarle nel modo ritenuto più opportuno.
Link utile: documentazione msdn