Le avventure in VB.Net di un principiante ex-VB6 - 13
a cura di Oscar Zanin e Diego Cattaruzza (requisiti: Visual Basic Express e SqlServer)Premessa
Dopo la critica di Diego alla form di ricerca di Oscar - argomento del precedente articolo - c'è voluto un po' di tempo perché fosse pronta la correzione di Oscar e ancora di più tempo a Diego per le proprie considerazioni, poiché nel frattempo vari impegni accavallatisi hanno impedito una sollecita pubblicazione di questo articolo.In questa puntata verrà illustrata la parte della FrmRicerca che interagisce con le altre form, in modo da terminare lo sviluppo della FrmStati.
La logica di funzionamento
La FrmRicerca è una finestra di dialogo che deve restituire alla form chiamante una lista di stringhe contenente i valori dei campi chiave necessari alla visualizzazione del record selezionato in fase di ricerca dall'utente.La FrmRicerca espone una serie di caselle combinate (di numero e contenuto variabili) tramite le quali impostare una ricerca i cui risultati vengono esposti in una griglia.
L'utente sceglie (o no) un record, in base al quale viene compilata la lista dei campi chiave.Come tutte le finestre di dialogo, FrmRicerca deve restituire un DialogResult. Quindi bisogna predisporre una proprietà per la lista dei campi chiave. La form chiamante, quando il controllo del programma torna ad essa alla chiusura della FrmRicerca, legge questa proprietà per i propri scopi (sempre che il DialogResult sia DialogResultOk).
La FrmRicerca deve funzionare per ciascuna form del progetto che ne possa aver bisogno, quindi deve essere in grado di autoconfigurarsi in base alla form chiamante. Occorre cioè un insieme di informazioni che la form chiamante possa preparare e poi passare alla FrmRicerca affinché questa possa autoconfigurarsi. Questo insieme costituisce la struttura InfoRicerca.
In base all'analisi svolta da Diego nel precedente articolo, Oscar ha modificato la struttura propostagli da Diego aggiungendo qualche membro e migliorandone l'impostazione e l'uso.
Questa struttura va posta nello stesso modulo della FrmRicerca, certamente il posto più adatto. Non è cioè il caso di creare un file a parte. Quindi creiamo la base della FrmRicerca. La completeremo in seguito.La FrmRicerca - prima parte
In Esplora soluzioni clicchiamo con il tasto destro sul progetto PrimiPassi, selezioniamo la voce Aggiungi e quindi Nuovo elemento. Nella finestra che appare, nella sezione Modelli personali selezioniamo Krypton Form, assegnamo come nome FrmRicerca e clicchiamo sul pulsante Aggiungi.
- KryptonManager (già presente)
- - GlobalPaletteMode = Office 2007 - Blue
- FrmRicerca:
- - Eliminiamo il KryptonPanel presente all'interno della form
- - BackColor = (Web) LightBlue
- - FormBorderStyle = FixedDialog
- - Icon = Cerca.ico (dalla cartella Immagini)
- - KeyPreview = True
- - MaximizeBox = False
- - MinimizeBox = False
- - Size = 800;500
- - StartPosition = CenterParent
- - Text = Ricerca
- Trasciniamo un controllo ToolStrip
- - Name = TbrStrumenti
- - ImageScalingSize = 32; 32 (dimensione in pixel delle immagini che utilizzeremo)
- - aggiungiamo un primo Button
- - Name = BtnEsci
- - Image = dai File di risorse del progetto selezioniamo l'immagine Pulsanti_Uscita
- - Text = Esci
- - aggiungiamo un Separator
- - aggiungiamo un secondo Button
- - Name = BtnFiltra
- - Image = dai File di risorse del progetto selezioniamo l'immagine Pulsanti_Filtra
- - Text = Filtra dati
- - Enabled = False
- - aggiungiamo un terzo Button
- - Name = BtnSvuota
- - Image = dai File di risorse del progetto selezioniamo l'immagine Pulsanti_Svuota
- - Text = Svuota criteri e griglia
- - Enabled = False
- - aggiungiamo un Separator
- - aggiungiamo un quarto Button
- - Name = BtnConferma
- - Image = dai File di risorse del progetto selezioniamo l'immagine Pulsanti_InserisciRiga
- - Text = Conferma
Per il momento basta così. Le Label, le ComboBox e la DataGridView verranno aggiunte in fase di esecuzione, sulla base della struttura di informazioni che stiamo per implementare.
La struttura InfoRicerca
Per non creare confusione con il codice pertinente la form di ricerca, faremo buon uso delle Region e, per fornire a Intellisense le più ampie possibilità di aiutarci, commenteremo ogni membro (nel contempo, i commenti stessi aiutano nella comprensione dell'articolo):Public Class FrmRicerca End Class #Region "RicercaHelper" #Region "Strutture" ''' <summary> ''' Inforicerca: struttura principale di informazioni per la form di ricerca ''' </summary> ''' <remarks>fa uso di altre strutture</remarks> Public Structure InfoRicerca ''' <summary> ''' Titolo per la FrmRicerca ''' </summary> Dim TitoloForm As String ''' <summary> ''' Nome della tabella di riferimento ''' </summary> Dim NomeTabella As String ''' <summary> ''' Ordinamento dei dati visualizzati nella griglia ''' </summary> Dim Ordinamento As String ''' <summary> ''' Insieme delle strutture di informazioni per i criteri di filtro ''' </summary> ''' <remarks>vedi struttura Criterio</remarks> Dim Criteri As List(Of Criterio) ''' <summary> ''' Insieme delle strutture di informazioni per le colonne della griglia ''' </summary> ''' <remarks>vedi struttura Colonna</remarks> Dim Colonne As List(Of Colonna) End StructureNella Region RicercaHelper distinguiamo una Region Strutture, perché la struttura InfoRicerca usa altre due strutture, una per le informazioni relative alle Combobox per i criteri di selezione e l'altra per quelle relative alle colonne della DataGridView.
''' <summary> ''' Criterio: struttura informazioni per le combobox e le label ''' con le quali si impostano i criteri di filtro ''' </summary> ''' <remarks>fa uso di due enumerati: TipoOrigineDati e TipoConfronto</remarks> Public Structure Criterio ''' <summary> ''' Testo della Label descrittiva del criterio ''' </summary> ''' <remarks></remarks> Dim Etichetta As String ''' <summary> ''' Tipo di origine dei dati per l'elenco della combobox ''' </summary> ''' <remarks>vedi enumerato TipoOrigineDati. ''' Se Filtro, Valori deve avere un elemento; ''' se ElencoValori, Valori deve avere questo elenco</remarks> Dim OrigineDati As TipoOrigineDati ''' <summary> ''' Nome del campo i cui valori vengono visualizzati ''' </summary> Dim NomeCampoVisualizzato As String ''' <summary> ''' Nome del campo i cui valori vengono utilizzati ''' </summary> Dim NomeCampoValore As String ''' <summary> ''' Tipo Sql del campo ''' </summary> Dim TipoCampoValore As SqlDbType ''' <summary> ''' Indica se deve essere validata la scelta fatta tramite la ComboBox ''' </summary> Dim ControlloValidita As Boolean ''' <summary> ''' Tipo di confronto per l'operazione di filtro ''' </summary> ''' <remarks>vedi enumerato TipoConfronto</remarks> Dim Confronto As TipoConfronto ''' <summary> ''' Elementi dell'elenco della Combobox, se OrigineDati è diverso da DatiTabella ''' </summary> ''' <remarks>Opzionale. Se OrigineDati è Filtro, Valori deve avere un elemento; ''' se OrigineDati è ElencoValori, Valori deve avere questo elenco</remarks> Dim Valori As String() Sub New(ByVal etichetta As String, ByVal origineDati As TipoOrigineDati, _ ByVal nomeCampoVisualizzato As String, ByVal nomeCampoValore As String, _ ByVal tipoCampoValore As SqlDbType, ByVal controlloValidita As Boolean, _ ByVal confronto As TipoConfronto, Optional ByVal valori As String() = Nothing) Me.Etichetta = etichetta Me.OrigineDati = origineDati Me.NomeCampoVisualizzato = nomeCampoVisualizzato Me.NomeCampoValore = nomeCampoValore Me.TipoCampoValore = tipoCampoValore Me.ControlloValidita = controlloValidita Me.Confronto = confronto Me.Valori = valori End Sub End StructureCome si può notare, sono stati implementati anche due enumerati, che vedremo in seguito, dopo la terza struttura:
''' <summary> ''' Colonna: struttura informazioni per la griglia ''' </summary> Public Structure Colonna ''' <summary> ''' Nome del campo esposto nella colonna ''' </summary> Dim NomeCampo As String ''' <summary> ''' Intestazione della colonna ''' </summary> Dim Intestazione As String ''' <summary> ''' Larghezza della colonna ''' </summary> Dim Larghezza As Integer ''' <summary> ''' Indica se la colonna deve essere di tipo CheckBox ''' </summary> Dim CheckBox As Boolean ''' <summary> ''' Indica se la colonna deve essere visibile ''' </summary> Dim Visibile As Boolean ''' <summary> ''' Indica se il valore deve essere restituito nel vettore per la form chiamante ''' </summary> ''' <remarks>E' importante indicare come chiave ogni campo restituito alla form chiamante, ''' Non necessariamente solo quelli della chiave univoca della tabella</remarks> Dim Chiave As Boolean ''' <summary> ''' Tipo Sql del campo ''' </summary> Dim TipoCampo As SqlDbType Sub New(ByVal nomeCampo As String, ByVal intestazione As String, ByVal larghezza As Integer, _ ByVal checkBox As Boolean, ByVal visibile As Boolean, ByVal chiave As Boolean, _ ByVal tipoCampo As SqlDbType) Me.NomeCampo = nomeCampo Me.Intestazione = intestazione Me.Larghezza = larghezza Me.CheckBox = checkBox Me.Visibile = visibile Me.Chiave = chiave Me.TipoCampo = tipoCampo End Sub End Structure #End RegionPer le due ultime strutture è più che opportuno predisporre un costruttore. L'ultimo parametro del costruttore della struttura Criterio è opzionale, per evidenti ragioni.
Oltre alla Region Strutture, c'è una Region Enumerati, di cui si fa uso nella struttura Criterio.#Region "Enumerati" ''' <summary> ''' Tipo di origine dei dati per l'elenco della combobox ''' </summary> ''' <remarks>usato nella struttura Criterio</remarks> Public Enum TipoOrigineDati ''' <summary> ''' l'unico elemento nel parametro Valori fa da filtro fisso ''' </summary> ''' <remarks>la combobox è disabilitata</remarks> Filtro ''' <summary> ''' gli elementi della lista della combobox sono elencati nel parametro Valori ''' </summary> ElencoValori ''' <summary> ''' gli elementi della lista della combobox sono tratti da una tabella ''' </summary> DatiTabella End Enum ''' <summary> ''' Tipo di confronto per l'operazione di filtro ''' </summary> ''' <remarks>in base ad esso si costruiscono le clausole WHERE</remarks> Public Enum TipoConfronto Uguale Maggiore MaggioreUguale Minore MinoreUguale End Enum #End Region #End RegionLa FrmRicerca - seconda parte
Adesso possiamo rifinire la FrmRicerca aggiungendo le direttive Imports e il costruttore necessario:#Region "Dichiarazione degli imports" Imports APP.Base Imports APP.Data Imports APP.Data.ConvalidaDati Imports APP.UI Imports System.Data.SqlClient #End RegionAPP.Base serve per accedere al metodo ValQ, App.Data per accedere alla ConnessioneDatabase e a metodi della classe ConvalidaDati, APP.UI per la classe Messaggi.
Ed ecco lo scheletro della FrmRicerca:Public Class FrmRicerca #Region "Variabili private" Private mInfoRicerca As InfoRicerca #End Region #Region "Proprietà" Private mCampiChiave As New List(Of String) Public ReadOnly Property CampiChiave() As List(Of String) Get Return mCampiChiave End Get End Property #End Region #Region "Costruttori" Private Sub New() InitializeComponent() End Sub Public Sub New(ByVal inforicerca As InfoRicerca) InitializeComponent() mInfoRicerca = inforicerca Me.Text = mInfoRicerca.TitoloForm PreparaCriteri() PreparaGriglia() End Sub #End Region #Region "Metodi di servizio" Private Sub PreparaCriteri() ' End Sub Private Sub PreparaGriglia() ' End Sub #End Region End ClassIl primo costruttore - quello di default, che sostituisce quello presente nel file FrmRicerca.Designer.vb, da cancellare - viene imposto privato per renderlo inaccessibile e quindi per rendere obbligatorio l'uso del secondo, quello che richiede il parametro InfoRicerca, che è indispensabile. Nel codice, si valorizza la relativa variabile privata (mInfoRicerca), si imposta il titolo della form e si completa la form con la creazione degli altri controlli (Label e ComboBox per i criteri secondo cui impostare la ricerca, la DataGridView per mostrare i risultati della ricerca impostata).
La FrmRicerca espone la proprietà di sola lettura CampiChiave, destinata a contenere i dati richiesti dalla form chiamante.
La FrmStati - Richiamo della FrmRicerca
A questo punto abbiamo predisposto tutto quel che serve per terminare lo sviluppo della FrmStati.
E' il momento infatti di implementare il codice per il pulsante BtnCerca:Private Sub BtnCerca_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles BtnCerca.Click Dim ir As InfoRicerca ir.TitoloForm = "Ricerca Stato" ir.NomeTabella = "Stati" ir.Ordinamento = "Stato" ir.Criteri = New List(Of Criterio) ir.Criteri.Add(New Criterio("Stato", TipoOrigineDati.DatiTabella, "Stato", "Stato", _ SqlDbType.VarChar, False, TipoConfronto.Uguale)) ir.Colonne = New List(Of Colonna) ir.Colonne.Add(New Colonna("Stato", "Stato", 290, False, True, True, SqlDbType.VarChar)) Dim frm As New FrmRicerca(ir) Dim risposta As DialogResult = frm.ShowDialog() Dim campiChiave As List(Of String) If risposta = Windows.Forms.DialogResult.OK Then campiChiave = frm.CampiChiave Else Exit Sub End If If campiChiave.Count = 0 Then Exit Sub End If Dati.ResettaValoriChiavi() For i As Integer = 0 To campiChiave.Count - 1 Dati.AggiungiValoreChiave(campiChiave(i).ToString) Next Dati.TrovaRecord() VisualizzaDati() End SubCome si può vedere, si imposta una struttura InfoRicerca, poi la si passa all'istanza della FrmRicerca, prima di aprire questa come dialogo.
Se al ritorno si ha un DialogResult.OK, la lista dei campi chiave per trovare il record che si cerca dovrebbe essere popolata, nel qual caso adoperiamo i già noti metodi della classe Tabella per giungere a visualizzare i dati richiesti.Naturalmente, non è proprio con FrmStati che si può apprezzare la funzionalità della struttura InfoRicerca e della FrmRicerca, dato che abbiamo a che fare con un solo campo, ma a questo punto della serie è importante capire l'interazione tra questa fondamentale form di dialogo e le altre form del progetto.
Conclusione
In questa puntata è stata illustrata la parte della FrmRicerca che interagisce con le altre form, in modo da terminare lo sviluppo della FrmStati.Nella prossima puntata si concluderà l'illustrazione della FrmRicerca.
Il codice di PrimiPassi sviluppato fino a questo momento è come al solito disponibile in area download.
Anche per questa puntata, Diego mette a disposizione nel suo blog un post cui scrivere critiche, suggerimenti, richieste di chiarimento.