VB.NET Esempi di base su Data Binding WPF (it-IT)
Scopo
Questo articolo si propone di introdurre al concetto base di Data Binding in WPF, presentando a titolo di esempio il popolamento di una DataGrid (da lista di struttura personalizzata) e sua successiva modifica tramite TextBox, a loro volta traenti la fonte dati dalla griglia stessa.
Introduzione
È ormai noto come una delle maggiori caratteristiche e novità introdotte con Windows Presentation Foundation risieda nella possibilità di collegare con semplicità i controlli utente (e non solo) a fonti dati più o meno complesse, lasciando all'ambiente il compito di eseguirne la rappresentazione (su cui si potrà comunque sempre operare). Per esemplificare un possibile scenario di utilizzo, supporremo qui di dover eseguire la rappresentazione in griglia di una determinata struttura personalizzata e - successivamente - di doverne rendere possibile l'editazione attraverso dei semplici controlli testuali.
Una classe di esempio
Supponiamo di disporre di una ipotetica classe Articolo, la quale ci permetterà la definizione di prodotti da catalogare, nei termini di codice articolo, descrizione, data di scadenza. Definiremo la classe - riduttiva, ma utile ai nostri fini - come segue:
Public Class Articolo Dim _codice As String Dim _descrizione As String Dim _datascadenza As Date Public ReadOnly Property Codice As String Get Return _codice End Get End Property Public Property Descrizione As String Get Return _descrizione End Get Set(value As String) _descrizione = value End Set End Property Public Property DataScadenza As Date Get Return _datascadenza End Get Set(value As Date) _datascadenza = value End Set End Property Public Sub New(codart As String, desart As String) _codice = codart _descrizione = desart _datascadenza = New Date(Now.Year + 1, Now.Month, Now.Day) End Sub End Class |
Si noti che nel costruttore della classe vengono richiesti solo i parametri codice e descrizione, e che la data di scadenza viene calcolata impostando un anno nel futuro a partire da oggi. Le proprietà che definiscono la classe sono modificabili, eccezion fatta per il codice articolo, che non può essere variato una volta creato.
Il prossimo passo sarà costituito dal popolare una lista di articoli con alcuni dati di esempio, utili per i prossimi passi. Ipotizziamo di aver a disposizione una finestra WPF di nome MainWindow.xaml. Creeremo un gestore di eventi per l'evento Loaded, in modo che lo XAML della finestra risulti simile a quanto segue:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ERP_test" x:Class="MainWindow" Title="MainWindow" Height="269" Width="563" Loaded="Window_Loaded"> </Window> |
Il codice sottostante l'evento sarà:
Dim prodotti As List(Of Articolo) Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) prodotti = New List(Of Articolo) prodotti.Add(New Articolo("Prodotto01", "ARTICOLO TEST")) prodotti.Add(New Articolo("Prodotto02", "PROVA")) prodotti.Add(New Articolo("Prodotto03", "NESSUNA DESCRIZIONE")) End Sub |
Molto semplicemente, quindi, disporremo di una List(Of Articolo) globale alla finestra, di nome prodotti, che conterrà inizialmente tre articoli. Tale struttura rappresenta la base dati che esporremo, tramite data binding, ad una DataGrid. Vediamo come.
Data Binding su DataGrid
Nella nostra finestra aggiungeremo un controllo DataGrid, dal nome arbitrario di DataGrid1. Disponendo di una struttura lato codice, sarà necessario agire su questo versante per collegare il controllo alla sua sorgente dati. Tale connessione (binding) si ottiene sfruttando la proprietà ItemsSource del controllo. Il nostro evento Loaded verrà pertanto modificato come segue:
Dim prodotti As List(Of Articolo) Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) prodotti = New List(Of Articolo) prodotti.Add(New Articolo("Prodotto01", "ARTICOLO TEST")) prodotti.Add(New Articolo("Prodotto02", "PROVA")) prodotti.Add(New Articolo("Prodotto03", "NESSUNA DESCRIZIONE")) DataGrid1.ItemsSource = prodotti End Sub |
ItemsSource, infatti, è quella proprietà (di tipo System.Collections.IEnumerable) attraverso cui andiamo ad indicare (o leggere) una raccolta dati da utilizzarsi per generare il contenuto di un determinato controllo (in questo caso, della griglia). Il binding dei dati sulla DataGrid è concluso: da una prima esecuzione del nostro modulo, vedremo un risultato simile a questo:
Data Binding tra controlli: Datagrid su TextBox e DatePicker
Come descritto in apertura, non siamo però unicamente interessati ad avere una lista di prodotti, ma desideriamo fare in modo che - scorrendo tale lista - venga visualizzato il dettaglio del record selezionato. A questo proposito utilizzeremo alcuni TextBox, eseguendo un loro binding a partire dalla DataGrid, e facendo in modo che essa venga a sua volta modificata dall'eventuale variazione operata sui TextBox (o DatePicker, nel caso della data di scadenza). Modifichiamo quindi la nostra finestra come segue:
Le proprietà che nei TextBox e DatePicker espongono il valore mostrato a video sono, rispettivamente, Text e SelectedDate. È pertanto necessario che il data binding venga effettuato su tali proprietà. In sostanza, individuata la proprietà che deve ricevere un dato, si dovrà indicarne l'origine, più altre informazioni (alcune delle quali opzionali) che determineranno il modo in cui i dati vengono scambiati. Nel nostro caso, desiderando che tramite la variazione dei tre nuovi controlli venga aggiornato anche il contenuto della DataGrid, dovremo fare in modo che il data binding sia bidirezionale.
Trattandosi di operazioni che verranno effettuate tra controlli, è possibile intervenire direttamente sul codice XAML, indicando come i TextBox ed il DatePicker debbano essere collegati con la DataGrid. Il codice relativo ai tre controlli verrà modificato come segue:
<TextBox HorizontalAlignment="Left" Height="23" Margin="445,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="181" Text="{Binding SelectedItem.Codice,ElementName=DataGrid1 , Mode=OneWay }"/> <TextBox HorizontalAlignment="Left" Height="23" Margin="445,70,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="181" Text="{Binding SelectedItem.Descrizione,ElementName=DataGrid1 , Mode=TwoWay }"/> <DatePicker HorizontalAlignment="Left" Margin="445,98,0,0" VerticalAlignment="Top" Width="181" SelectedDate="{Binding SelectedItem.DataScadenza,ElementName=DataGrid1 , Mode=TwoWay }"/> |
Come accennato, le proprietà che espongono un certo dato devono essere valorizzate indicando la sorgente ed il modo in cui verranno reperiti i dati. Prendiamo a titolo di esempio il caso 1, ovvero relativo al TextBox che espone il codice articolo:
Si nota, in questo caso, che il controllo di origine è impostato su DataGrid1, dalla quale verrà letta la proprietà Codice (appartenente alla classe Articolo) dell'elemento selezionato. La modalità di binding è mono-direzionale, ovvero va dall'origine (DataGrid1) alla destinazione (TextBox), e non viceversa: questo perché, come abbiamo impostato nella classe Articolo, Codice è una proprietà di sola lettura, ed il tentativo di modificarla solleverebbe pertanto un'eccezione.
Analogamente, negli altri due casi avremo sempre DataGrid1 come controllo di origine, le proprietà saranno ovviamente le restanti Descrizione e DataScadenza, ma la modalità di binding sarà TwoWay, ovvero bidirezionale: la modifica del contenuto del controllo produrrà un aggiornamento della proprietà di origine dello stesso, ovvero DataGrid1 (e, per estensione, della lista ad esso collegata).
Eseguendo quindi il nostro programma, e provando a posizionarci per esempio sul secondo record, per poi variarne i dati, verificheremo il corretto aggiornamento dei dati del controllo collegato:
Naturalmente qui abbiamo discusso di un piccolo esempio rispetto alle possibilità offerte da questa tecnologia: ad ogni modo mi auguro sia stato utile a chi si approccia per le prime volte a questo metodo. Happy coding!