Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1908, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Sviluppare Metro-style app per Windows 8 con Visual Basic - quinta parte

Nel precedente post di questa serie abbiamo creato un'app in stile Metro per Windows 8 che legge i feed RSS dal Visual Basic Developer Center di MSDN e abbiamo cominciato a prendere confidenza con il pattern Async, con classi specifiche di WinRT e con l'esecuzione dell'app.

In questo post (il nr. 1500!) facciamo degli interessanti passi in avanti, implementando caratteristiche tipiche di Windows 8: lo Share contract e l'app bar.

Share contract

Come sapete le app Metro godono della possibilità di integrarsi profondamente con il sistema operativo e con altre app, condividendo informazioni. Questo è possibile attraverso i cosiddetti charm (condivisione, ricerca, impostazioni) attivabili passando il puntatore del mouse in basso a destra o usando il touch scorrendo dolcemente il dito dal lato destro del device. I charm sono ciò che vede l'utente, ma dal lato dello sviluppatore ci sono delle apposite API chiamate contracts.

Lo Share contract sostanzialmente consente all'app di condividere un contenuto o un'informazione con altre app o con il sistema. Pensate banalmente a una foto da voler condividere con un'app di social networking o con il client di posta.  

Ciò che ci proponiamo di raggiungere oggi, quindi, è la possibilità di condividere i contenuti scaricati dalla nostra app con altre app in grado di ricevere i contenuti stessi. Nota bene: lo Share contract può essere duplice, nel senso che un'app può sia inviare che ricevere contenuti. Noi implementeremo la sola condivisione, per semplicità di apprendimento.

Il namespace Windows.ApplicationModel.DataTransfer espone la classe DataTransferManager che offre gli strumenti adatti all'implementazione del contract. In altre parole:

  • ottenuta l'istanza della classe DataTransferManager, si ottiene l'istanza dei contenuti visualizzati
  • si sottoscrive l'evento DataTransferRequested
  • quest'ultimo viene scatenato quando l'utente attiva il charm di condivisione
  • si impostano le proprietà della condivisione e il contratto fa il resto

Il che si traduce nel seguente codice da digitare nel code-behind della nostra (per ora) unica pagina:

    'Some initialization values
    Private dataPackageTitle As String = "Default Title"
    Private dataPackageDescription As String = "Default Description"
    Private dataPackageUri As Uri = Nothing
 
    Private datatransferManager As DataTransfer.DataTransferManager
    Private Sub ShareSourceLoad()
        Try
            'Get the current view for sharing
            datatransferManager = DataTransfer.DataTransferManager.GetForCurrentView()
            'Subscribe to the DataRequested event which is raised when the user attempts to share a content
            AddHandler datatransferManager.DataRequested, AddressOf datatransferManager_DataRequested
        Catch
 
        End Try
    End Sub
 
    Private Sub datatransferManager_DataRequested(sender As DataTransferManager, e As DataRequestedEventArgs)
        Dim currentFeed = CType(Me.itemListView.SelectedItem, FeedItem)
 
        dataPackageTitle = currentFeed.Title
        dataPackageDescription = currentFeed.Content
        dataPackageUri = currentFeed.Link
 
        e.Request.Data.Properties.Title = dataPackageTitle
        e.Request.Data.Properties.Description = dataPackageDescription
 
        'Actual sharing here
        e.Request.Data.SetUri(dataPackageUri)
 
    End Sub

Come vedete, il gestore dell'evento assegna alcune proprietà dell'oggetto e.Request che è quello che attiva lo sharing nel momento in cui si invoca il metodo SetUri. A tal proposito è bene evidenziare che il metodo ShareSourceLoad va invocato nel costruttore:

    Public Sub New()
 
        ' This call is required by the designer.
        InitializeComponent()
 
        ' Add any initialization after the InitializeComponent() call.
        ShareSourceLoad()
    End Sub

In realtà la user interface relativa alla condivisione può essere invocata anche da codice, ragion per la quale aspettiamo di vedere in azione il codice precedente dopo aver implementato l'app bar. In ogni caso, con questi pochi passaggi Windows automaticamente fornirà l'elenco di applicazioni che sono in grado di ricevere il contenuto condiviso. Il che significa che Windows non consentirà di condividere un link con un'app per foto, facendo così un lavoro egregio.

"Vuole il menu o sa già?" - L'app bar e i comandi

E' chiaro che anche in un'app Metro ci deve essere la possibilità di offrire dei comandi attraverso dei pulsanti. Mentre nelle classiche applicazioni desktop abbiamo i menu (o recentemente il Ribbon), in Metro si ha la cosiddetta app bar che è una barra a scomparsa sulla quale definiamo i comandi da offrire.

Nel nostro caso metteremo due pulsanti: uno per visualizzare il contenuto del feed in un'anteprima Web migliore e uno per attivare lo share contract da codice (per fini didattici). A questo punto occorre fare un'importante considerazione: i pulsanti nell'app bar devono essere, chiaramente, in stile Metro con delle apposite icone.

Per fortuna Visual Studio 11 ci toglie da un gran bell'impiccio, fornendo tutte le icone di uso più comune direttamente in codice XAML contenuto nel file Common\StandardStyles.xaml.

Non serve riportare pedissequamente quel codice qui, vi basta esplorare il file. Degno di nota è il fatto che viene definito uno stile base chiamato AppBarButtonStyle, dal quale ereditano poi i vari altri stili.

Ovviamente non sempre gli stili standard soddisfano le nostre necessità di conseguenza è possibile definire degli stili personalizzati. Posto quindi che avremo due pulsanti, uno al quale assegneremo un'icona standard e uno al quale assegneremo un'icona custom, definiamo un'icona personalizzata per rappresentare la preview Web. Il codice è ripreso dalla documentazione che vi ho già linkato in precedenza e va inserito nelle risorse della pagina:

        <Style x:Key="WebViewAppBarButtonStyle" TargetType="Button" 
           BasedOn="{StaticResource AppBarButtonStyle}">
            <Setter Property="AutomationProperties.AutomationId" Value="WebViewAppBarButton"/>
            <Setter Property="AutomationProperties.Name" Value="View Web Page"/>
            <Setter Property="Content" Value="&#xE12B;"/>
        </Style>

Due cose: AutomationProperties.Name andrà ad identificare il pulsante con un identificatore, mentre Content rappresenta il modo in cui l'icona deve essere disegnata. Le possibilità di definizione della proprietà Value sono discusse nella documentazione.

L'app bar, per praticità, può essere definita prima della Grid principale ed è rappresentata da un oggetto AppBar che necessariamente va all'interno di un contenitore chiamato Page.TopAppBar se vogliamo che questa risieda nell'area superiore o Page.BottomAppBar se vogliamo che risieda in quella inferiore. Nel nostro caso è fatta così:

        <Page.TopAppBar>
            <AppBar Padding="10,0,10,0">
                <Grid>
 
                    <Button Click="ViewDetail_Click" HorizontalAlignment="Right" 
                    Style="{StaticResource WebViewAppBarButtonStyle}"/>
                    <Button Name="ShareButton" Click="ShareButton_Click_1" Style="{StaticResource MailAppBarButtonStyle}" HorizontalAlignment="Left"/>
                </Grid>
            </AppBar>
        </Page.TopAppBar>

Quindi come vedete l'app bar contiene due pulsanti definiti nel modo consueto, che puntano a due gestori di evento Click. Notate come lo style vada a fare riferimento a quello custom e a quello predefinito.

Passando ai gestori di evento, innanzitutto vediamo come sia possibile richiamare da codice il charm della condivisione con un metodo statico chiamato ShowShareUI:

    Private Sub ShareButton_Click_1(sender As Object, e As RoutedEventArgs)
        Dim currentFeed = CType(Me.ItemListView.SelectedItem, FeedItem)
 
        dataPackageTitle = currentFeed.Title
        dataPackageDescription = currentFeed.Content
        dataPackageUri = currentFeed.Link
 
        datatransferManager.ShowShareUI()
    End Sub

Si ottiene semplicemente l'istanza del feed, si popolano le proprietà, si invoca l'interfaccia grafica da codice. Poi si passa all'altro pulsante:

    Private Sub ViewDetail_Click(sender As Object, e As RoutedEventArgs)
        Dim selectedItem As FeedItem = Me.ItemListView.SelectedItem
        If selectedItem IsNot Nothing And Me.Frame IsNot Nothing Then
            RemoveHandler datatransferManager.DataRequested, AddressOf datatransferManager_DataRequested
            Me.Frame.Navigate(GetType(WebPreviewItemsPage), selectedItem)
        End If
    End Sub

L'oggetto Frame rappresenta il modo con cui controlliamo la navigazione tra pagine. Il suo metodo Navigate permette di aprire la pagina il cui nome/oggetto è il primo argomento, mentre il secondo rappresenta il dato da passare. Chiaramente la pagina di destinazione sarà definita a momenti, ma voglio prima sottolineare la necessità di rimuovere la sottoscrizione all'evento DataRequested poiché quando si ritorna alla pagina principale, il Runtime tenta di sottoscriverlo ancora e rimuoverla serve ad evitare eccezioni.

Navigazione tra pagine

Avete già sviluppato per Windows Phone? Bravi  Pur se con un'infrastruttura di oggetti diversa, in Metro esiste il concetto di pagina e di navigazione. Esiste un framework che permette di spostarsi tra pagine e che addirittura espone metodi per tornare alla pagina principale e di controllo sul fatto che tornare indietro sia possibile.

Aggiungiamo quindi al progetto un nuovo elemento di tipo Basic Page, un template nel quale viene ereditata la classe LayoutAwarePage che offre l'infrastruttura sopra citata:

Una volta creato il nuovo elemento con il nome come in figura, andiamo a definire lo XAML:

        <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="140"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
 
            <!-- Back button and page title -->
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Button x:Name="backButton" Click="GoBack" 
                    IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" 
                    Style="{StaticResource BackButtonStyle}"/>
                <TextBlock x:Name="pageTitle" Grid.Column="1" 
                       Text="{Binding Title}" 
                       FontSize="26.667"
                       Margin="12,20,12,2"/>
            </Grid>
            <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                Grid.Row="1" Margin="120,15,20,20">
                <WebView x:Name="contentView" />
            </Border>
 
            <!-- Omissis .... -->
 
        </Grid>

Ho omesso tutta la parte relativa al Visual State Manager che Visual Studio ha generato. Qui è importante sottolineare ancora l'utilizzo del WebView per la visualizzazione e il fatto che il pulsante per tornare alla pagina precedente sia in binding con uno specifico metodo chiamato GoBack che non c'è necessità di implementare perché definito già nella classe base; stesso dicasi per il CanGoBack che abilita il pulsante se il suo stato è True. A questo punto dobbiamo dire alla pagina come trattare i dati che la pagina chiamante ha inviato.

Si fa l'override del metodo OnNavigatedTo, in un modo simile al seguente:

    Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
        ' Add this code to navigate the web view to the selected blog post.
        Dim _feedItem As FeedItem = e.Parameter
        If _feedItem IsNot Nothing Then
            Me.contentView.Navigate(_feedItem.Link)
            Me.DataContext = _feedItem
        End If
    End Sub

L'oggetto e.Parameter riceve i dati dalla pagina chiamante; questi vengono convertiti in un oggetto FeedItem e il relativo link viene passato al controllo WebView. A questo punto possiamo finalmente testare l'app!

Test dell'app

Ecco quindi che tornano familiari le immagini presentate nel post precedente. L'app bar (che per i test col mouse potete attivare col tasto destro):

 E lo Share contract:

Vi invito a fare un test reale dello sharing, selezionando ad esempio il client di posta elettronica, per capire come la tecnica funzioni.

Conclusioni

In questo lunghissimo post abbiamo quindi visto due caratteristiche specifiche di Windows 8, ossia l'interazione con uno dei charm e l'app bar. In realtà manca un tassello, che è la definizione dell'orientamento dell'app in base alla rotazione del dispositivo, che vedremo nel prossimo post.

Download del codice

Ogni promessa è debito e poiché siete stati pazienti, questo è il link per scaricare il codice sorgente del progetto dimostrato finora. Preciso che il codice già contiene anche le modifiche che faremo nel prossimo post, così avrete una traccia utile da seguire.

Alessandro

Print | posted on venerdì 27 aprile 2012 02:26 | Filed Under [ Visual Basic UWP e Windows Store Apps Visual Studio 2012 ]

Powered by:
Powered By Subtext Powered By ASP.NET