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

LINQ: validare i dati con il controllo ErrorProvider in Visual Basic

In questo post vediamo come implementare, in un’applicazione data-bound, la validazione dei dati immessi in una DataGridView tramite il controllo ErrorProvider, utilizzando LINQ-to-SQL.

Ho preso spunto da questo progetto della mitica Beth Massi, rielaborandolo in modo semplificato e velocizzato, al fine di avere meno confusione nell’implementazione e focalizzare l’attenzione sui concetti “caldi” (Beth considera, invece, un più complesso esempio di tipo master-detail). Innanzitutto dovete avere a disposizione il database Northwind.

Dopodiché, dovete creare un’applicazione Windows Forms collegata a Northwind e nella quale sia implementata una classe LINQ-to-SQL. Se questi passaggi sono per voi una novità, potete leggere il mio articolo introduttivo a LINQ-to-SQL su Visual Basic Tips & Tricks. La tabella che prenderemo in considerazione è quella dei Customers, da trascinare, quindi, sulla superficie della classe LINQ-to-SQL.

La tabella Customers, quindi, costituisce la sorgente dati che deve essere collegata all’applicazione e successivamente trascinata sul form al fine di ottenere la generazione automatica di oggetti BindingNavigator e BindingSource.

Sempre nel designer, va aggiunto un controllo ErrorProvider; il valore della sua proprietà DataSource va impostata su CustomersBindingSource, ossia l’oggetto riferibile alla sorgente dati generato dall’IDE.

Lo scopo della dimostrazione, infatti, è quello di mostrare un simbolo di errore (tipico dell’ErrorProvider) allorquando l’utente inserisce i dati di un nuovo customer ma non ne specifica la città. A tal proposito si può progettare una classe che implementi l’interfaccia IDataErrorInfo, che permette di manipolare informazioni sugli errori da associare poi all’interfaccia utente. Chiameremo questa classe Validazione e, al suo interno,  scriveremo dei metodi per la gestione di errori. E’ consigliabile, anche se non obbligatorio, metterla in un file apposito:

Public Class Validazione

    Implements IDataErrorInfo

 

    'Collection di tipo key/value per memorizzare la locazione

    'dove si è verificato l'errore e il messaggio da mostrare

    Private validationErrors As New Dictionary(Of String, String)

 

    'Aggiunge un errore alla collection, specificando la colonna

    'e un messaggio

    Protected Sub AddError(ByVal columnName As String, ByVal msg As String)

        If Not validationErrors.ContainsKey(columnName) Then

            validationErrors.Add(columnName, msg)

        End If

    End Sub

 

    'Rimuove dalla collection ciascun errore a partire

    'dal nome della colonna specificato

    Protected Sub RemoveError(ByVal columnName As String)

        If validationErrors.ContainsKey(columnName) Then

            validationErrors.Remove(columnName)

        End If

    End Sub

 

    'Proprietà per determinare se la collection contiene errori

    Public Overridable ReadOnly Property HasErrors() As Boolean

        Get

            Return (validationErrors.Count > 0)

        End Get

    End Property

 

 

    Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error

        Get

            If validationErrors.Count > 0 Then

                Return String.Format("{0}: errori nei dati.", TypeName(Me))

            Else

                Return Nothing

            End If

 

        End Get

    End Property

 

    Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item

        Get

            If validationErrors.ContainsKey(columnName) Then

                Return validationErrors(columnName).ToString

            Else

                Return Nothing

            End If

        End Get

    End Property

End Class

I metodi AddError e RemoveError verranno richiamati da un’altra locazione che descriveremo tra breve. L’interfaccia IDataErrorInfo espone due proprietà da implementare, chiamate Error ed Item. La prima serve a descrivere cosa c’è di sbagliato, mentre la seconda determina il messaggio da associare all’oggetto che riceve come argomento.  Nel nostro caso, la proprietà Error verifica che il numero di elementi nella collection validationErrors sia maggiore di zero (quindi, che siano elencati degli errori). Item, invece, restituisce un messaggio relativo alla colonna specificata della DataGridView.

Il passaggio successivo è quello di aggiungere alla classe Customers, generata dall’IDE, la chiamata ai metodi per la validazione dei dati. In questa fase possiamo sfruttare una novità di Visual Basic 2008, costituita dai partial methods, che vanno ad aggiungersi alle partial classes introdotte con Visual Basic 2005. Se attivate la visualizzazione di tutti i file in Esplora soluzioni e andate a curiosare nel file Northwind.designer.vb, noterete che, per la classe Customers, c’è una #Region chiamata Extensibility Methods Definitions. Questa contiene tutta una serie di definizione di metodi “parziali” che sottendono ai cambiamenti che vengono attuati sulle proprietà (colonne) costituenti la classe Customers (tabella) la quale, allo scopo, implementa le proprietà INotifyPropertyChanging e INotifyPropertyChanged.

 Analogamente a quanto avviene per le classi, i metodi parziali possono essere suddivisi su più file di codice. A noi può interessare, ad esempio, il metodo parziale OnCityChanging, all’interno del quale andremo a richiamare la validazione dell’inserimento della città per ciascun nuovo customer. L’IDE ha aggiunto un altro file, chiamato Northwind.vb. Questo contiene la classe parziale Customers, che va a completare la parte vista nel file Northwind.designer.vb. All’interno di questa classe parziale andremo a completare il lavoro. Innanzitutto questa deve ereditare dalla classe che implementa l’interfaccia IDataErrorInfo, quindi la nostra classe Validazione. Potremmo scriverla così (commenti di seguito):

Partial Class Customers

    Inherits Validazione

 

    Private Sub OnCityChanging(ByVal value As String)

        CheckCity(value)

    End Sub

 

    'Quando viene richiamato il metodo Validate sul Form..

    Private Sub OnValidate(ByVal action As System.Data.Linq.ChangeAction)

        CheckCity(Me.City)

 

        If Me.HasErrors Then

            Throw New Exception(Me.Error)

        End If

    End Sub

 

    Private Sub CheckCity(ByVal value As String)

        'se la stringa è vuota

        If String.IsNullOrEmpty(value) Then

            'Aggiunge un errore

            AddError("City", "Il campo città non può essere vuoto.")

        Else

            RemoveError("City")

        End If

    End Sub

 

    'Ridefinisce la proprietà HasErrors della classe base

    Public Overrides ReadOnly Property HasErrors() As Boolean

        Get

            Return MyBase.HasErrors

        End Get

    End Property

 

End Class

Fondamentale importanza riveste il metodo CheckCity, che costituisce il nodo della verifica dei dati. Se la stringa ricevuta come argomento (quindi la proprietà City della tabella Customers) è vuota, aggiunge un errore alla collection precedentemente definita. Questo metodo viene richiamato nell’ambito della notifica di cambiamenti sulle proprietà della tabella e alla richiesta di validazione dei dati. Nel codice del form principale può essere implementato un metodo di questo tipo, che verifica la presenza di errori nei dati:

    Private Sub DisplayErrors()

        Me.ErrorProvider1.UpdateBinding()

        Me.CustomersDataGridView.Refresh()

 

        If Me.CustomersBindingSource.Position > -1 Then

 

            'Ottiene il customer corrente

            Dim currentCustomer As Customers = CType(Me.CustomersBindingSource.Current, Customers)

 

            'Se non contiene errori

            If Not currentCustomer.HasErrors Then

                'vuol dire che non è nella griglia, quindi va a cercarlo

                For i = 0 To Me.CustomersBindingSource.Count - 1

                    Dim customer As Customers = CType(Me.CustomersBindingSource(i), Customers)

                    If customer.HasErrors Then

                        Me.CustomersBindingSource.Position = i

                        Exit Sub

                    End If

                Next

            End If

        End If

    End Sub

Dopo aver reso attivo (proprietà Enabled) del pulsante di salvataggio sul BindingNavigator, i dati vanno verificati nel gestore del suo evento Click, prima di inviarli al database per l’aggiornamento:

    Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click

        Me.Validate()

 

        CustomersBindingSource.EndEdit()

 

        Try

            'Invia i cambiamenti al database

            dc.SubmitChanges()

        Catch ex As Exception

 

            'Controlla la presenza di errori

            Me.DisplayErrors()

            MessageBox.Show("Si è verificato un errore di validazione")

        End Try

    End Sub

Avviando l’applicazione, provate ad aggiungere un nuovo customer, lasciando in bianco la proprietà City. Oltre ad essere avvisati da una dialog, il tipico simbolo dell’ErrorProvider mostrerà dove si trova l’errore e, passando col puntatore del mouse su di esso, una tooltip mostrerà l’errore da noi specificato:

 

Ovviamente, per popolare la griglia non dovete dimenticare di aggiungere un riferimento al DataContext:

    Private dc As New NorthwindDataContext

 

 

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        CustomersBindingSource.DataSource = dc.Customers

    End Sub

Alessandro

Print | posted on domenica 13 aprile 2008 21:57 | Filed Under [ Visual Basic LINQ ]

Powered by:
Powered By Subtext Powered By ASP.NET