|
Funzionamento
Questo controllo permette di navigare attraverso insiemi di dati, siano essi tabelle di database o semplici liste di oggetti non fa differenza,
permettendo di visualizzare o modificare una qualsiasi delle loro proprietà e di aggiungere od eliminare uno qualsiasi dei suoi elementi.
La particolarità che lo distingue da qualsiasi altro controllo del genere (come potrebbero essere ListView o DataGridView) consiste
nel fatto che la sua interfaccia non è una tabella: anzi, è a priori indefinita. Se si considera poi il fatto che aggiungerlo
semplicemente al form non porterà alcun risultato, si potrebbe pensare che BindingNavigator è proprio una fregatura XD
In effetti, per vederlo funzionare correttamente bisogna aggiungere un po' di altri controlli e scrivere qualche riga di codice. Infatti,
ho appena detto che esso permette di navigare attraverso un insieme di dati e visualizzare tali dati su una certa interfaccia grafica che
per ora non conosciamo: le incognite, quindi, sono due, ossia da dove attingere i dati e come visualizzarli. Per questo motivo,
sono necessari almeno altri due componenti. Il primo di questi è un controllo BindingSource, il quale, come già visto nel
capitolo precedente, si preoccupa di gestire e mediare l'interazione con una certa risorsa di informazioni. Il secondo (e gli altri eventuali)
è arbitrario e dipende dalla natura dei dati da visualizzare: per delle stringhe, ad esempio, avremo bisogno di una TextBox.
Autori illustri...
Per esemplificare il comportamento di BindingNavigator, ecco una semplice applicazione che permette di visualizzare una serie di grandi nomi
e le loro opere principali. La nostra fonte di dati sarà una lista di oggetti di tipo Author, classe così definita:
Public Class Form1
Public Class Author
Private _Name As String
Private _Works As List(Of String)
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Public ReadOnly Property Works() As List(Of String)
Get
Return _Works
End Get
End Property
Public Sub New()
_Works = New List(Of String)
End Sub
Public Sub New(ByVal Name As String, ByVal ParamArray WorksNames() As String)
Me.New()
Me.Name = Name
Me.Works.AddRange(WorksNames)
End Sub
End Class
Public Authors As New List(Of Author)
End Class
Ora aggiungiamo al form un BindingNavigator di nome bnMain:

All'aspetto sembra solo una toolstrip con qualche button, due label e una textbox. È questo, e anche di più.
Aggiungiamo ora un BindingSource di nome bsData e impostiamo la proprietà bsMain.BindingSource su bsData. Aggiungete altri controlli
in modo che l'interfaccia sia la seguente:

Vorremo usare il pulsanti freccia del binding navigator per spostarci avanti e indietro nella lista, e i rispettivi pulsanti per aggiungere
o eliminare un elemento. Il codice:
Public Class Form1
Public Class Author
Private _Name As String
Private _Works As List(Of String)
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Public ReadOnly Property Works() As List(Of String)
Get
Return _Works
End Get
End Property
Public Sub New()
_Works = New List(Of String)
End Sub
Public Sub New(ByVal Name As String, ByVal ParamArray WorksNames() As String)
Me.New()
Me.Name = Name
Me.Works.AddRange(WorksNames)
End Sub
End Class
Public Authors As New List(Of Author)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Aggiungie alcuni elementi iniziali alla lista
Authors.Add(New Author("Dante Alighieri", "Comed?a", "Vita Nova", "De vulgari eloquentia", "De Monarchia"))
Authors.Add(New Author("Luigi Pirandello", "Il fu Mattia Pascal", "Uno, nessuno, centomila", "Il gioco delle parti"))
'Imposta la sorgente di dati del bindingsource
bsAuthors.DataSource = Authors
'Aggiunge un binding alla textbox. Ciò significa
'che la proprietà Text di txtName sarà da
'ora in poi sempre legata alla proprietà Name
'dell'elemento corrente della sorgente di dati di
'bsAuthors. Dato che quest'ultima è una lista di
'Author, ogni suo elemento espone la proprietà
'Name.
txtName.DataBindings.Add("Text", bsAuthors, "Name")
'Non possiamo fare la stessa cosa con lstWorks.Items,
'poiché Items è una proprietà readonly.
'Questo capita abbastanza spesso: si ha bisogno di
'visualizzare una lista per ogni elemento dell'insieme.
'La soluzione consiste nel caricare gli items della
'lista quando viene caricato un nuovo elemento
End Sub
Private Sub bsAuthors_CurrentChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bsAuthors.CurrentChanged
'L'evento CurrentChanged si verifica quando la proprietà
'Current del binding source viene modificata. Ciò significa
'che l'utente si è spostato tramite il binding
'navigator. Ottenendo l'oggetto Current, possiamo risalire alla
'lista di stringhe che esso contiene
Dim Author As Author = bsAuthors.Current
lstWorks.Items.Clear()
lstWorks.Items.AddRange(Author.Works.ToArray())
End Sub
Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
'Aggiunge alla listbox e alla lista Works un nuovo
'titolo aggiunto dall'utente
If Not String.IsNullOrEmpty(txtAdd.Text) Then
lstWorks.Items.Add(txtAdd.Text)
DirectCast(bsAuthors.Current, Author).Works.Add(txtAdd.Text)
txtAdd.Text = ""
End If
End Sub
Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
'Elimina una delle opere visualizzate
If lstWorks.SelectedIndex >= 0 Then
DirectCast(bsAuthors.Current, Author).Works.RemoveAt(lstWorks.SelectedIndex)
lstWorks.Items.RemoveAt(lstWorks.SelectedIndex)
End If
End Sub
End Class
Come vedete, il codice è molto ridotto anche se l'applicazione supporta un numero più elevato di funzionalità: tutto
ciò che non abbiamo scritto viene automaticamente gestito dal BindingNavigator.
La proprietà DataBindings, per inciso, non appartiene solo a TextBox, ma a tutti i controlli e non è necessario specificare
come sorgente di dati un binding source, ma un qualsiasi oggetto, poiché tutto viene gestito tramite reflection. È possibile
associare una qualsiasi proprietà di un controllo ad un campo di un qualsiasi altro oggetto.
Allo stesso modo, è possibile associare alla proprietà DataSource di BindingSource una tabella di un database, o un dataset
(e associate un dataset, dovrebe usare la proprietà DataMember per specificare quale tabella). |
|