Creare app per l'accesso locale ai dati in Windows Phone Mango con Visual Basic 2010
a cura di Alessandro Del Sole (requisiti: media conoscenza di connessione a dati, LINQ To SQL)Introduzione
Nel precedente articolo abbiamo fatto un'introduzione abbastanza rapida dell'ambiente di sviluppo per Windows Phone 7.5 (Mango) in Visual Studio 2010.
In questo articolo ci addentriamo in modo specifico all'interno di una delle novità più importanti della nuova versione e sicuramente di una delle più richieste dall'utenza, ossia la possibilità di creare applicazioni che accedano a dei dati locali organizzati in un database.Prima di Mango, infatti, gli sviluppatori avevano solo due possibilità di interagire con basi di dati strutturate: lavorare con file XML (o altri formati) da memorizzare nell'Isolated Storage del dispositivo, oppure ricorrere a SQL Azure, il database nel Cloud. Con l'avvento di Mango, invece, il sistema operativo supporta la versione 3.5 di SQL Server Compact Edition, quella che, per intenderci, viene normalmente distribuita con Visual Studio 2010.Questo fatto chiaramente offre dei grandissimi vantaggi, quali la possibilità di avere un sistema per la gestione di dati collaudato ed affidabile, che permette di lavorare in maniera strutturata e che ben si adatta allo spazio messo a disposizione da un dispositivo mobile.
Un'altra buona notizia è che per accedere ai dati in Windows Phone utilizzeremo un modello di programmazione a noi caro e noto: LINQ. In modo particolare bisogna utilizzare LINQ to SQL, che per sua natura è il provider decisamente più adatto al contesto.
In questo articolo impareremo quindi ad utilizzare SQL Compact in Windows Phone Mango, con Visual Basic 2010. Il codice a corredo dell'articolo è disponibile in area Download di Visual Basic Tips & Tricks. La dotazione software richiesta è stata compiutamente elencata nel precedente articolo, in ogni caso è sufficiente utilizzare Visual Studio 2010 Express per Windows Phone.
I dati, LINQ, le classi
Ci sono un paio di operazioni preliminari da compiere prima di mettere le mani su Visual Studio. Innanzitutto, il database. E' chiaramente possibile crearne uno nuovo a seconda delle proprie esigenze, utilizzando gli strumenti Microsoft all'uopo preposti come SQL Server Management Studio, ma questo esula dagli scopi di questo articolo. Per praticità è possibile ricorrere al database dimostrativo Northwind.sdf, che si trova nella cartella C:\Programmi\Microsoft SQL Server Compact Edition\v3.5\Samples. E' conveniente fare una copia di questo file in una cartella che sia al di fuori dell'User Access Control di Windows 7/Vista, come ad esempio la classica C:\Temp. Fatto questo, è necessario generare il modello a oggetti basato su LINQ to SQL.Mentre per tutte le altre tipologie di applicazioni in Visual Studio abbiamo a disposizione l'apposito designer (vedi questo vecchio articolo), nello sviluppo per Windows Phone il designer per LINQ to SQL non è disponibile. La soluzione è quindi l'utilizzo di un tool a riga di comando chiamato SQLMetal.exe, che appartiene agli strumenti di Visual Studio e che l'IDE stesso utilizza per generare gli object model. Per lanciare SQLMetal, avviamo dapprima il prompt dei comandi di Visual Studio 2010 attraverso l'apposito collegamento disponibile in Start/Programmi/Microsoft Visual Studio 2010/Tools. All'avvio del command prompt digitiamo la seguente riga:
SQLMetal.exe C:\Temp\Northwind.sdf /language:vb /code:NorthwindDataClasses.vb /pluralize /context:NorthwindDataContext /Namespace:Northwind
Dopo aver specificato il pathname del database, si specifica il linguaggio (/language), il file di codice che conterrà le classi generate (/code), la richiesta di generare nomi al plurale per le tabelle a seconda delle regole della grammatica inglese (/pluralize) e il nome per la classe di tipo DataContext (/context). Fatto questo, passiamo a Visual Studio.
Creare il progetto
Indipendentemente dall'edizione utilizzata (Express per Windows Phone o superiori), il progetto da creare in Visual Basic è di tipo Windows Phone Application.
Una volta che il progetto è stato creato, aggiungiamo un riferimento all'assembly System.Data.Linq.dll, necessario per il supporto a LINQ to SQL.
A questo punto possiamo aggiungere al progetto il file appena creato con SQLMetal, che contiene le definizioni delle classi che costituiscono il nostro modello a oggetti. Selezioniamo quindi Project/Add Existing Item e selezioniamo il file NorthwindDataClasses.vb. Quando questo è stato aggiunto a Visual Studio potrete notare il lungo elenco delle classi che mappano le tabelle e le proprietà delle classi che mappano le colonne delle tabelle.In particolare, è necessario rimuovere i due seguenti overload del costruttore poiché non sono supportati in Mango e verranno evidenziati come errati:
Public Sub New(ByVal connection As System.Data.IDbConnection)
MyBase.New(connection, mappingSource)
OnCreated()
End Sub
Public Sub New(ByVal connection As System.Data.IDbConnection, _
ByVal mappingSource As System.Data.Linq.Mapping.MappingSource)
MyBase.New(connection, mappingSource)
OnCreated()
End SubDefinizione dell'interfaccia grafica
Definiamo ora l'interfaccia grafica, per poi passare alla gestione dei dati.
L'interfaccia grafica di quest'applicazione sarà abbastanza essenziale. L'idea è infatti quella di concentrarci sul codice che esegue le operazioni sui dati, lasciando all'interfaccia solo un compito minimale di presentazione dei dati stessi. Supponiamo di voler lavorare con la tabella Customers e di volerne visualizzare alcune colonne. All'interno del contenitore Grid chiamato ContentPanel, possiamo utilizzare il controllo ListBox e definire al suo interno un c.d. data template che ci permetta di definire con quali controlli dovranno essere presentate le informazioni. Ecco il codice:<ListBox HorizontalAlignment="Left" Name="ListBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding CompanyName}"/>
<TextBlock Text="{Binding City}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>Il codice è molto semplice, sebbene presupponga una minima conoscenza di XAML. Sostanzialmente abbiamo una griglia divisa in due colonne, ognuna delle quali contiene un TextBlock collegato in binding con proprietà provenienti dall'origine dati.
Cogliamo anche l'occasione per illustrare l'utilizzo di un'altra funzionalità dell'interfaccia del dispositivo, nota come application bar, ossia quell'area in basso sulla pagina che contiene piccoli pulsanti rotondi. Per default Visual Studio aggiunge una serie di righe di codice per l'interazione con tale barra e che sono commentate. Sostituiamole con le seguenti:
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton x:Name="AddButton" Click="AddButton_Click"
IconUri="/Images/appbar_button1.png" Text="Aggiungi"/>
<shell:ApplicationBarIconButton x:Name="RemoveButton" Click="RemoveButton_Click"
IconUri="/Images/appbar_button2.png" Text="Rimuovi"/>
<shell:ApplicationBarIconButton x:Name="FilterButton" Click="FilterButton_Click"
IconUri="/Images/appbar_button3.png" Text="Filtra"/>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>Come si può osservare è stato specificato un nome (x:Name) per ciascun pulsante e un gestore di evento per l'evento Click, unitamente al testo descrittivo (Text). Utilizzando l'application bar possiamo evitare di definire dei pulsanti ad hoc. Dopo aver definito l'interfaccia, per quanto essenziale, passiamo alla logica dell'applicazione.
La gestione dei dati
La logica dell'applicazione si svolge chiaramente, almeno in questo caso, all'interno del code-behind della pagina principale. C'è da definire la stringa di connessione al database e l'istanza del DataContext. Consideriamo il seguente codice:Private connectionString As String = "Data Source=isostore:/Northwind.sdf"
Private northwindContext As Northwind.NorthwindDataContext
' Constructor
Public Sub New()
InitializeComponent()
Me.northwindContext = New Northwind.NorthwindDataContext(connectionString)
If Not Me.northwindContext.DatabaseExists Then
northwindContext.CreateDatabase()
End If
End SubLa variabile connectionString definisce la stringa di connessione, che è molto semplice. L'identificatore isostore è fisso e sta ad identificare l'isolated storage di Windows Phone. La variabile northwindContext mantiene il riferimento al DataContext di LINQ to SQL, che viene in realtà istanziato nel costruttore passando come argomento di istanza la stringa di connessione. Si noti come il codice seguente verifichi l'esistenza del database e come lo crei nel caso in cui questo non sia già esistente. Non dimentichiamo di rilasciare le risorse nel momento in cui l'applicazione termina, nel nostro caso è sufficiente farlo all'evento Unloaded della pagina principale:
Private Sub MainPage_Unloaded(sender As Object, e As System.Windows.RoutedEventArgs) _
Handles MyBase.Unloaded
Me.northwindContext.Dispose()
End SubPossiamo poi facilmente gestire l'evento Click del pulsante di aggiunta, all'interno del quale, sempre per finalità dimostrative, andiamo a creare quattro nuovi oggetti Customer che vengono aggiunti al DataContext (InsertOnSubmit) e inviati al database nel momento del salvataggio (SubmitChanges):
Private Sub AddButton_Click(sender As System.Object, e As System.EventArgs)
Try
Dim c1 As New Northwind.Customer With {.CompanyName = "Del Sole",
.City = "Roma", .CustomerID = "DELSO"}
Dim c2 As New Northwind.Customer With {.CompanyName = "Marzaro",
.City = "Varese", .CustomerID = "MARZA"}
Dim c3 As New Northwind.Customer With {.CompanyName = "Catucci",
.City = "Milano", .CustomerID = "CATUC"}
Dim c4 As New Northwind.Customer With {.CompanyName = "Cattaruzza",
.City = "Trieste", .CustomerID = "CATTA"}
northwindContext.Customers.InsertOnSubmit(c1)
northwindContext.Customers.InsertOnSubmit(c2)
northwindContext.Customers.InsertOnSubmit(c3)
northwindContext.Customers.InsertOnSubmit(c4)
northwindContext.SubmitChanges()
'Popola la ListBox con la tabella
Me.ListBox1.ItemsSource = northwindContext.Customers
Catch ex As System.Data.Linq.DuplicateKeyException
MessageBox.Show("Tentativo di inserimento dati duplicati")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End SubSi noti come intercettare la DuplicateKeyException permette di evitare l'inserimento di dati che abbiano una chiave primaria duplicata. La ListBox viene popolata assegnando alla proprietà ItemsSource la tabella Customers.
Nel gestore di evento Click del pulsante di rimozione, invece, otteniamo l'istanza dell'oggetto selezionato nella ListBox e, se non è un oggetto nullo, la rimuoviamo:
Private Sub RemoveButton_Click(sender As System.Object, e As System.EventArgs)
Dim currentCustomer = TryCast(Me.ListBox1.SelectedItem, Northwind.Customer)
If currentCustomer Is Nothing Then Exit Sub
northwindContext.Customers.DeleteOnSubmit(currentCustomer)
northwindContext.SubmitChanges()
Me.ListBox1.ItemsSource = Nothing
Me.ListBox1.ItemsSource = northwindContext.Customers
End SubSi noti che la doppia assegnazione ad ItemsSource (prima a Nothing e poi con la sorgente dati appena modificata) è dovuta al fatto che il controllo non verrebbe altrimenti aggiornato automaticamente.
Infine, dimostriamo come eseguire una query LINQ che filtri i dati in base al criterio specificato:
Private Sub FilterButton_Click(sender As System.Object, e As System.EventArgs)
Me.ListBox1.ItemsSource = New ObservableCollection(Of Northwind.Customer)((
From cust In northwindContext.Customers
Where cust.CompanyName.StartsWith("C")
Select cust))
End SubTest dell'applicazione
Ora avviamo l'applicazione premendo F5 e attendiamo che questa venga eseguita all'interno dell'emulatore Windows Phone. Eseguiamo in sequenza le operazioni di aggiunta, filtro, eliminazione. La seguente figura mostra un esempio:
![]()
Come potete vedere, i dati vengono correttamente aggiunti, eliminati e filtrati esattamente come ci aspetteremmo, il tutto in un vero database locale.
Conclusioni
Avere la possibilità di gestire un database locale apre a infiniti scenari di sviluppo mobile e conferma la bontà delle novità di Windows Phone Mango. Considerazione non di poco conto, strumenti di sviluppo e database SQL Compact sono gratuiti.
Per ulteriori informazioni potete visitare il mio blog o contattarmi al mio indirizzo email.