Le avventure in VB.Net di un principiante ex-VB6 - 19
a cura di Oscar Zanin e Diego Cattaruzza (requisiti: Visual Basic Express e SqlServer)Premessa
In questo articolo completeremo la descrizione dello sviluppo della prima form master-details, la FrmClienti, iniziata nell'articolo precedente, in cui sono state illustrate le sue parti 'accessorie', classi dati e form di dialogo.Un enumerato per le griglie
In questa form sono presenti due griglie e si è reso necessario indicare a quale (quali) griglie riferirsi nel codice. Quindi, prima di cominciare lo sviluppo della FrmClienti, apriamo il file ConvalidaDati.vb e aggiungiamo in fondo il seguente enumerato:Public Enum GrigliaDaPreparare Prima Seconda Terza Tutte End EnumIl disegno della FrmClienti
Dopo aver aggiunto una nuova Krypton Form di nome FrmClienti al progetto PrimiPassi, dovete scegliere quale aspetto dare alla form, poiché essa contiene una notevole quantità di controlli. Mentre Oscar ha dovuto - su specifica richiesta del cliente, il quale, per quanto stupido possa essere, ha sempre ragione - disegnare una form piuttosto grande (1265x790) con tutti i dati contemporaneamente visibili, Diego ha distribuito gli stessi controlli su due schede di un controllo a schede, contenendo le dimensioni (800x600).
Nelle seguenti figure, sono mostrate le due versioni (le immagini sono anteprime opportunamente dimensionate, cliccando sulle quali vedrete le form nella dimensione originale).Stavolta, dato l'alto numero di controlli, è preferibile che diate semplicemente una buona occhiata alle immagini, mentre per il disegno, invece di seguire un lunghissimo elenco di impostazioni (che omettiamo proprio per la sua lunghezza), procedete in questo modo:
- Salvate la FrmClienti, anche vuota e chiudete la finestra di disegno (file FrmClienti.vb);
- aprite il file FrmClienti.Designer.vb;
- sostituite completamente il contenuto con quello di uno dei due file di testo forniti (con lo stesso nome più l'estensione .txt): ozFrmClienti.Designer.vb.txt (la form di Oscar) e FrmClienti.Designer.vb.txt (quella di Diego, che è quella adottata nel progetto, dato che non abbiamo un cliente stupido)
In tal modo potrete seguire la successiva implementazione del codice. Il codice della ozFrmClienti di Oscar è quello originale, mentre quello della FrmClienti è quello revisionato da Diego. In tal modo avete la possibilità di fare confronti e cercare di capire il motivo delle differenze (di solito solo cosmetiche).
Nel seguito si fa riferimento alla FrmCllienti, non alla ozFrmClienti.Il codice della FrmClienti
Premettendo che non sempre si è potuto ri-formattare il codice in modo da renderlo meglio leggibile (quindi aspettatevi qualche punto da leggere con pazienza e attenzione), cominciamo con le direttive di importazione:#Region "Dichiarazione degli imports" Imports APP.Data Imports APP.Data.SqlHelper Imports APP.Data.ConvalidaDati Imports APP.Data.ConversioneTipo Imports APP.UI Imports APP.UI.Formattazione Imports APP.PrimiPassi.Dettagli Imports System.Data.SqlClient #End RegionTra le quali si fa notare APP.PrimiPassi.Dettagli, il namespace creato nell'articolo precedente.
Dopo la dichiarazione dell'evento ActiveControlChanged, che ormai dovreste conoscere, ecco i campi:Private Dati As DatiMasterDetails Private mOperazione As TipoOperazione Private mPulisciControlli As SvuotaControlli Private mBancaCorrente As String Private mSediCliente As New List(Of ClientiSedi) ' nuove Sedi Private mRiferimentiCliente As New List(Of ClientiRiferimenti) ' nuovi RiferimentiStavolta, il campo Dati è di tipo DatiMasterDetails, non di tipo Tabella; di mOperazione e di mPulisciControlli dovreste ormai sapere tutto.
Il campo mBancaCorrente serve da deposito per indurre uno specifico comportamento: esso viene valorizzato al momento dell'ingresso nella casella combinata relativa al nome della banca (evento Enter); al momento dell'uscita (evento Leave) si controlla se il contenuto è stato modificato, nel qual caso si fa una ricerca nella tabella delle banche: se si trova una sola corrispondenza, si compilano le caselle dell'agenzia, dell'ABI e del CAB; se vengono trovate più occorenze di quella banca, si apre la form di ricerca e si fa selezionare all'utente, fra le sue, l'agenzia che desidera, con conseguente popolamento dei controlli relativi.
I campi mSediCliente e mRiferimentiCliente sono insiemi delle classi dati già esposte nell'articolo precedente che servono a gestire inserimenti, modifiche, cancellazioni di righe nelle due griglie.Private Sub frmClienti_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Try mOperazione = TipoOperazione.Nessuna mPulisciControlli = New SvuotaControlli 'Impostazione classe Master-Dettagli Dati = New DatiMasterDetails(ConnessioneDatabase, "Clienti")Tra le prime operazioni svolte, dopo l'inizializzazione di due campi, viene creata l'istanza della DatiMasterdetails (anziché della classe Tabella, come in FrmStati). Ricordiamo che, comunque, DatiMasterdetails usa Tabella. Se ritenete opportuno un veloce ripasso, per comprendere i passi successivi, se ne è parlato nelle puntate 9 (Tabella) e 10 (DatiMasterdetails).
Nellle righe successive si impostano proprietà della tabella master e si aggiungono le tabelle di dettaglio facendosi restituire l'indice per riferirisi a esse, si imposta l'ordinamento dei dettagli e le relazioni tra master e detail.
'Impostazione Master Dati.NomeCampoModificaMaster = "Modifica" Dati.OrdinamentoMaster = "Codice" 'Impostazione Dettagli - Clienti_Sedi Dim indice As Integer = Dati.AggiungiTabellaDettaglio("Clienti_Sedi") Dati.ImpostaOrdinamentoDettaglio(indice, "Codice, Nome, Citta") Dati.AggiungiRelazione(indice, "Codice", "Codice") 'Impostazione Dettagli - Clienti_Riferimenti indice = Dati.AggiungiTabellaDettaglio("Clienti_Riferimenti") Dati.ImpostaOrdinamentoDettaglio(indice, "Riferimento") Dati.AggiungiRelazione(indice, "Codice", "Codice")Quindi si caricano i dati e si popolano le griglie (notate il parametro di tipo GrigliaDaPreparare di cui sopra).
'Caricamento dati Dati.CaricaDati() 'Preparazione delle griglie PreparaGriglie(GrigliaDaPreparare.Tutte) VisualizzaDati()Concettualmente, i metodi PreparaGriglie e VisualizzaDati sono analoghi a quelli già incontrati precedentemente, soltanto un po' più laboriosi, dato l'elevato numero di campi. VisualizzaDati si differenzia per la chiamata finale al metodo PopolaGriglie. Ricordiamo, en passant, che in VisualizzaDati si sfrutta il metodo Value della classe ValoreCampo di cui alla puntata 17.
Mentre omettiamo, come ridondante, l'illustrazione dei metodi PreparaGriglie e VisualizzaDati - cosa che faremo anche per altri metodi del tutto simili a quelli analoghi sviluppati per le form a tabella singola - ci sembra il caso di parlare brevemente del metodo PopolaGriglie, di cui segue solo la prima parte, relativa alla griglia DgvSedi (la seconda parte, relativa alla griglia DgvRif, è analoga):Private Sub PopolaGriglie(ByVal griglia As GrigliaDaPreparare) ' sedi If griglia = GrigliaDaPreparare.Prima Or griglia = GrigliaDaPreparare.Tutte Then SvuotaGriglie(GrigliaDaPreparare.Prima) If mOperazione = TipoOperazione.Nessuna Then If Dati.DataSetDettaglio(0).Tables(0).Rows.Count > 0 Then For indr As Integer = 0 To Dati.DataSetDettaglio(0).Tables(0).Rows.Count - 1 Dim rigan As DataGridViewRow = New DataGridViewRow rigan.CreateCells(DgvSedi, New Object() _ { _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Codice"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Nome"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Indirizzo"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("CAP"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Citta"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Provincia"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Stato"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Telefono"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Fax"), _ Dati.DataSetDettaglio(0).Tables(0).Rows(indr)("Cellulare") _ }) DgvSedi.Rows.Add(rigan) Next indr End If Else If mSediCliente.Count > 0 Then For indr As Integer = 0 To mSediCliente.Count - 1 Dim rigan As DataGridViewRow = New DataGridViewRow rigan.CreateCells(DgvSedi, New Object() _ { _ mSediCliente(indr).Codice, _ mSediCliente(indr).RagSoc, _ mSediCliente(indr).Ind, _ mSediCliente(indr).Cap, _ mSediCliente(indr).Citta, _ mSediCliente(indr).Prov, _ mSediCliente(indr).Stato, _ mSediCliente(indr).Tel, _ mSediCliente(indr).Fax, _ mSediCliente(indr).Cel _ }) DgvSedi.Rows.Add(rigan) Next indr End If End If End IfCome potete vedere, si riceve un parametro che informa su quali griglie bisogna popolare e poi, per ciascuna griglia, si procede al popolamento: a seconda del tipo di operazione in corso (nessuna o qualcuna) si traggono nuove righe per la DataGridView dal dataset o dalla relativa lista di classi-dati.
Per quanto riguarda la form, è appena il caso di accennare che anche stavolta si gestisce l'evento Activated per richiamare il metodo PopolaCombo, e l'evento FormClosing per controllare se sia necessario un salvataggio.
Del metodo PopolaCombo riteniamo di qualche interesse commentare le prime righe:Private Sub PopolaCombo() Dim dstStato, dstPagam, dstBanca As DataSet Dim adp As SqlDataAdapter, cmd As SqlCommand Dim valoriPrec As String() = {CmbStato.Text, CmbPagam.Text, CmbBanca.Text}Dopo la dichiarazione degli oggetti Data, si popola un vettore di stringhe con i valori al momento contenuti nelle caselle combinate, in modo da ripristinarli dopo il caricamento. Un programmatore ex-VB6 potrebbe anche non conoscere questa comoda possibilità di assegnazione in linea.
Tra le gestioni degli eventi dei controlli nelle quali viene scatenato l'evento ActiveControlChanged, hanno qualche rilievo, come già accennato sopra, quelli relativi alla casella combinata CmbBanca:
Private Sub ElenchiATendina_Enter(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles CmbStato.Enter, CmbPagam.Enter, CmbBanca.Enter '... Select Case DirectCast(sender, ComboBox).Name '... Case "cmbBanca" mBancaCorrente = CmbBanca.Text '... End Select '... End SubIn fase di ingresso, viene depositato nel campo mBancaCorrente il valore attualmente mostrato in CmbBanca. Ad esso si fa poi riferimento in fase di uscita per per ottenere il comportamento già sopra descritto:
Private Sub CmbBanca_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) If CmbBanca.Text = mBancaCorrente Or CmbBanca.Text = String.Empty Then Exit Sub End If Dim dstAgenzie As DataSet Dim adp As SqlDataAdapter Dim cmd As SqlCommand Try 'Cerco l'agenzia corrispondente alla banca cmd = New SqlCommand() cmd.Connection = SqlHelper.ConnessioneDatabase cmd.CommandText = "SELECT Agenzia, ABI, CAB FROM Banche WHERE Banca = @Banca ORDER BY Agenzia" cmd.Parameters.AddWithValue("@Banca", CmbBanca.Text) cmd.Parameters("@Banca").SqlDbType = SqlDbType.VarChar adp = New SqlDataAdapter(cmd) dstAgenzie = New DataSet adp.Fill(dstAgenzie, "Agenzie") 'Valorizzo l'agenzia della banca If dstAgenzie.Tables(0).Rows.Count = 0 Then TxtAgenzia.Text = "" Exit Sub ElseIf dstAgenzie.Tables(0).Rows.Count = 1 Then ' se viene trovata una sola agenzia TxtAgenzia.Text = dstAgenzie.Tables(0).Rows(0).Item("Agenzia").ToString If Not dstAgenzie.Tables(0).Rows(0).Item("ABI") Is DBNull.Value Then TxtABI.Text = dstAgenzie.Tables(0).Rows(0).Item("ABI").ToString Else TxtABI.Text = String.Empty End If If Not dstAgenzie.Tables(0).Rows(0).Item("CAB") Is DBNull.Value Then TxtCAB.Text = dstAgenzie.Tables(0).Rows(0).Item("CAB").ToString Else TxtCAB.Text = String.Empty End If ElseIf dstAgenzie.Tables(0).Rows.Count > 1 Then ' se vengono trovate più agenzie Dim ir As InfoRicerca Dim filtro(0) As String ir.TitoloForm = "Ricerca Agenzia" ir.SorgenteDati = "SELECT Agenzia, ABI, CAB, Indirizzo, Citta, Provincia, Stato FROM Banche" ir.Ordinamento = "Agenzia" filtro(0) = CmbBanca.Text.ToString ir.Criteri = New List(Of Criterio) ir.Criteri.Add(New Criterio("Banca", TipoOrigineDati.Filtro, "Banca", "Banca", _ SqlDbType.VarChar, False, TipoConfronto.Uguale, "Banche", _ filtro)) ir.Colonne = New List(Of Colonna) ir.Colonne.Add(New Colonna("Agenzia", "Agenzia", 290, False, True, True, SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("ABI", "ABI", 50, False, True, False, SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("CAB", "CAB", 50, False, True, False, SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("Indirizzo", "Indirizzo", 290, False, True, False, _ SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("Citta", "Città", 290, False, True, False, SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("Provincia", "Prov.", 70, False, True, False, SqlDbType.VarChar)) ir.Colonne.Add(New Colonna("Stato", "Stato", 290, False, True, False, 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 'Valorizzo i campi dell'agenzia, dell'ABI e del CAB TxtAgenzia.Text = campiChiave(1) TxtABI.Text = campiChiave(2) TxtCAB.Text = campiChiave(3) End IfI commenti contenuti nel codice dovrebbero essere sufficienti, della FrmRicerca si è parlato nelle puntate a partire dalla tredicesima (nella dodicesima c'è solo una critica al codice originale, nella quindicesima c'è una correzione).
E' da notare come nel caso si trovino più agenzie la proprietà SorgenteDati dell'oggetto InfoRicerca non venga valorizzata con un nome di tabella del database, ma con una query e come l'unico Criterio passato alla FrmRicerca (per la sua ComboBox) abbia come tipo di origine dati filtro e come sia presente un valore nel vettore che nelle form descritte nelle precedenti puntate veniva lasciato vuoto. Il valore passato è naturalmente il nome della banca che l'utente ha digitato in CmbBanca.Private Sub BtnNuovo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnNuovo.Click 'Mi salvo il codice del record visualizzato in modo che 'se viene cliccato l'annulla torno a visualizzare quel record Dati.LeggiRecordMaster() 'Svuoto gli array di inserimento delle nuove righe e modifica delle esistenti per i dettagli mSediCliente.Clear() mRiferimentiCliente.Clear() BloccaBarra() SvuotaCampi() 'Imposto il codice Cliente TxtCodice.Text = NuovoCodice().ToString TxtNome.Select() mOperazione = TipoOperazione.Inserimento End SubIl codice per aggiungere un nuovo cliente, dopo aver salvato il record corrente e svuotato le liste di oggetti-dato, bloccato la barra e svuotato i controlli, usa il metodo NuovoCodice per ottenere il prossimo codice cliente usufruibile e proporlo all'utente.
Private Function NuovoCodice() As Integer Try 'Cerco il codice cliente più alto salvato Dim cmdTmp As New SqlCommand cmdTmp.Connection = ConnessioneDatabase cmdTmp.CommandText = "SELECT Codice FROM Clienti ORDER BY Codice DESC" ConnessioneDatabase.Open() Dim ris As Object = cmdTmp.ExecuteScalar() ConnessioneDatabase.Close() If ris Is DBNull.Value Or ris Is Nothing Then Return 1 End If Return Convert.ToInt32(ris) + 1Questo metodo ottiene l'ultimo codice dalla tabella Clienti; se non ci sono record, restituisce 1 (è il primo record), viceversa restituisce il numero successivo. Non è detto che questo sarà realmente il codice che verrà salvato per il nuovo cliente: infatti, per gestire la multiutenza e ridurre al minimo il problema della duplicazione dei record, questo metodo verrà chiamato nuovamente subito prima del salvataggio del record.
L'illustrazione del metodo per la gestione del click sul pulsante BtnModifica richiede un po' di attenzione:
Private Sub BtnModifica_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnModifica.Click 'Controllo se record è già stato variato If Not Dati.ImpostaModificaRecordMaster Then Exit Sub End If 'Svuoto gli array di inserimento delle nuove righe e modifica delle esistenti per i dettagli mSediCliente.Clear() mRiferimentiCliente.Clear() 'Compilo gli array di inserimento delle nuove righe e modifica delle esistenti 'per i dettagli con i dati precedentemente salvati 'Sedi For indr As Integer = 0 To Dati.DataSetDettaglio(0).Tables(0).Rows.Count - 1 AggiungiNuovoElementoASedi( _ ValoreCampo(Of Integer).Value(StringToInteger(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Codice").ToString), Integer.MaxValue), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Nome"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Indirizzo"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Citta"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("CAP"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Provincia"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Stato"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Telefono"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Fax"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(0).Tables(0).Rows(indr) _ ("Cellulare"), String.Empty)) Next indr 'Riferimenti For indr As Integer = 0 To Dati.DataSetDettaglio(1).Tables(0).Rows.Count - 1 AggiungiNuovoElementoARiferimenti( _ ValoreCampo(Of Integer).Value(StringToInteger(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("Codice").ToString), Integer.MaxValue), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("Riferimento"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("Telefono"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("Fax"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("Cellulare"), String.Empty), _ ValoreCampo(Of String).Value(Dati.DataSetDettaglio(1).Tables(0).Rows(indr) _ ("EMail"), String.Empty)) Next indr VisualizzaDati() BloccaBarra() TxtInd.Select() TxtCodice.ReadOnly = True mOperazione = TipoOperazione.Modifica End SubDopo aver verificato la possibilità di effettuare l'operazione e svuotato le liste di oggetti-dato, si passano a queste ultime i valori contenuti nella riga del dataset del dettaglio - preparandoli attraverso il metodo Value della classe ValoreCampo e, nel caso del codice, sfruttando anche il metodo StringToInteger della classe ConversioneTipo (vedi puntata 17).
Per questo scopo (aggiungere oggetti-dato alle liste) sono stati implementati specifici metodi:Private Sub AggiungiNuovoElementoASedi(ByVal codiceSede As Integer, _ ByVal ragSocSede As String, _ ByVal indSede As String, _ ByVal cittaSede As String, _ Optional ByVal capSede As String = "", _ Optional ByVal provSede As String = "", _ Optional ByVal statoSede As String = "", _ Optional ByVal telSede As String = "", _ Optional ByVal faxSede As String = "", _ Optional ByVal celSede As String = "") 'Controllo chiave duplicata For i As Integer = 0 To mSediCliente.Count - 1 If codiceSede = mSediCliente(i).Codice And ragSocSede = mSediCliente(i).RagSoc _ And cittaSede = mSediCliente(i).Citta Then Messaggi.Avviso("Sede già inserita !", "Attenzione") Exit Sub End If Next i Dim nuovaSede As New ClientiSedi 'Aggiungo un nuovo elemento alle sedi durante un nuovo inserimento nuovaSede.Codice = codiceSede nuovaSede.RagSoc = ragSocSede nuovaSede.Ind = indSede nuovaSede.Cap = capSede nuovaSede.Citta = cittaSede nuovaSede.Prov = provSede nuovaSede.Stato = statoSede nuovaSede.Tel = telSede nuovaSede.Fax = faxSede nuovaSede.Cel = celSede mSediCliente.Add(nuovaSede) End Sub Private Sub AggiungiNuovoElementoARiferimenti(ByVal codiceRif As Integer, _ ByVal rifRif As String, _ Optional ByVal telRif As String = "", _ Optional ByVal faxRif As String = "", _ Optional ByVal celRif As String = "", _ Optional ByVal mailRif As String = "") 'Controllo chiave duplicata For i As Integer = 0 To mRiferimentiCliente.Count - 1 If codiceRif = mRiferimentiCliente(i).Codice And rifRif = mRiferimentiCliente(i).Rif Then Messaggi.Avviso("Riferimento già inserito !", "Attenzione") Exit Sub End If Next i Dim rifNuovo As New ClientiRiferimenti 'Aggiungo un nuovo elemento ai riferimenti durante un nuovo inserimento rifNuovo.Codice = codiceRif rifNuovo.Rif = rifRif rifNuovo.Tel = telRif rifNuovo.Fax = faxRif rifNuovo.Cel = celRif rifNuovo.Mail = mailRif mRiferimentiCliente.Add(rifNuovo) End SubQuesti metodi ricevono i valori da assegnare alle proprietà dell'oggetto dato, sia esso di tipo ClientiSedi o ClientiRiferimenti; alcuni parametri, non essendo per campi a digitazione obbligatoria, sono opzionali.
Dapprima si controlla che l'oggetto non sia già presente nella lista (nel qual caso causerebbe eccezioni al momento di aggiornare il database), quindi, se non lo è, se ne crea uno nuovo, se ne valorizzano le proprietà e lo si aggiunge alla lista.
Questi metodi sono richiamati anche da pulsanti posti sotto le griglie, come vedremo nel seguito).Private Sub BtnConferma_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnConferma.Click Try If Not DatiValidi() Then Exit Sub Dim errori As Boolean = False If mOperazione = TipoOperazione.Inserimento Then 'Imposto il codice Cliente TxtCodice.Text = NuovoCodice.ToString End If CaricaRiga() If mOperazione = TipoOperazione.Inserimento Then Dati.AggiornaDataBase(DatiMasterDetails.TipoSalvataggio.SoloMaster) 'Salvo i dati delle Sedi If mSediCliente.Count > 0 Then errori = False Try For indRighe As Integer = 0 To mSediCliente.Count - 1 Dim riga As DataRow = Dati.RigaNuovaDettaglio(0) riga("Codice") = Integer.Parse(TxtCodice.Text) riga("Nome") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).RagSoc, String.Empty) riga("Indirizzo") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Ind, String.Empty) riga("CAP") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Cap, String.Empty) riga("Citta") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Citta, String.Empty) riga("Provincia") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Prov, String.Empty) riga("Stato") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Stato, String.Empty) riga("Telefono") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Tel, String.Empty) riga("Fax") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Fax, String.Empty) riga("Cellulare") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Cel, String.Empty) 'Aggiungo la riga al DataSet di dettaglio delle Sedi If Not Dati.AggiungiRigaNuovaDettaglio(0, riga) Then Messaggi.Errore(Dati.DescrizioneErrore, "Errore") errori = True End If Next indRighe Catch ex As Exception Messaggi.Errore(ex.ToString, "Errore") errori = True End Try End If If errori = False Then 'Salvo i dati dei Riferimenti If mRiferimentiCliente.Count > 0 Then Try For indRighe As Integer = 0 To mRiferimentiCliente.Count - 1 Dim riga As DataRow = Dati.RigaNuovaDettaglio(1) riga("Codice") = Integer.Parse(TxtCodice.Text) riga("Riferimento") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Rif, _ String.Empty) riga("Telefono") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Tel, _ String.Empty) riga("Fax") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Fax, _ String.Empty) riga("Cellulare") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Cel, _ String.Empty) riga("EMail") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Mail, _ String.Empty) 'Aggiungo la riga al DataSet di dettaglio dei Riferimenti If Not Dati.AggiungiRigaNuovaDettaglio(1, riga) Then Messaggi.Errore(Dati.DescrizioneErrore, "Errore") errori = True End If Next indRighe Catch ex As Exception Messaggi.Errore(ex.ToString, "Errore") errori = True End Try End If End If 'Salvo i dati dei dettagli If errori = False Then Dati.AggiornaDataBase(DatiMasterDetails.TipoSalvataggio.SoloDettagli) End If ElseIf mOperazione = TipoOperazione.Modifica Then 'Svuoto i DataTable precedenti Try For indRighe As Integer = 0 To Dati.DataSetDettaglio(0).Tables(0).Rows.Count - 1 Dati.DataSetDettaglio(0).Tables(0).Rows(indRighe).Delete() Next indRighe For indRighe = 0 To Dati.DataSetDettaglio(1).Tables(0).Rows.Count - 1 Dati.DataSetDettaglio(1).Tables(0).Rows(indRighe).Delete() Next indRighe Catch ex As Exception Messaggi.Errore(ex.ToString, "Errore") errori = True End Try If errori = False Then 'Salvo i dati delle Sedi If mSediCliente.Count > 0 Then errori = False Try For indRighe As Integer = 0 To mSediCliente.Count - 1 Dim riga As DataRow = Dati.RigaNuovaDettaglio(0) riga("Codice") = Integer.Parse(TxtCodice.Text) riga("Nome") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).RagSoc, String.Empty) riga("Indirizzo") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Ind, String.Empty) riga("CAP") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Cap, String.Empty) riga("Citta") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Citta, String.Empty) riga("Provincia") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Prov, String.Empty) riga("Stato") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Stato, String.Empty) riga("Telefono") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Tel, String.Empty) riga("Fax") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Fax, String.Empty) riga("Cellulare") = _ ValoreCampo(Of String).TryParseToDBNull(mSediCliente(indRighe).Cel, String.Empty) 'Aggiungo la riga al DataSet di dettaglio delle Sedi If Not Dati.AggiungiRigaNuovaDettaglio(0, riga) Then Messaggi.Errore(Dati.DescrizioneErrore, "Errore") errori = True End If Next indRighe Catch ex As Exception Messaggi.Errore(ex.ToString, "Errore") errori = True End Try End If End If If errori = False Then 'Salvo i dati dei Riferimenti If mRiferimentiCliente.Count > 0 Then Try For indRighe As Integer = 0 To mRiferimentiCliente.Count - 1 Dim riga As DataRow = Dati.RigaNuovaDettaglio(1) riga("Codice") = Integer.Parse(TxtCodice.Text) riga("Riferimento") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Rif, _ String.Empty) riga("Telefono") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Tel, _ String.Empty) riga("Fax") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Fax, _ String.Empty) riga("Cellulare") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Cel, _ String.Empty) riga("EMail") = _ ValoreCampo(Of String).TryParseToDBNull(mRiferimentiCliente(indRighe).Mail, _ String.Empty) 'Aggiungo la riga al DataSet di dettaglio dei Riferimenti If Not Dati.AggiungiRigaNuovaDettaglio(1, riga) Then Messaggi.Errore(Dati.DescrizioneErrore, "Errore") errori = True End If Next indRighe Catch ex As Exception Messaggi.Errore(ex.ToString, "Errore") errori = True End Try End If End If If errori = False Then Dati.AggiornaDataBase(DatiMasterDetails.TipoSalvataggio.Tutto) End If End If TxtCodice.ReadOnly = False Dati.CaricaDati() If Not Dati.TrovaRecord() Then Messaggi.Avviso("Il record appena salvato non è stato trovato !", "Salvataggio record") Else VisualizzaDati() End If mOperazione = TipoOperazione.Nessuna SbloccaBarra() TbrStrumenti.Select() 'Svuoto gli array di inserimento delle nuove righe e modifica delle esistenti per i dettagli mSediCliente.Clear() mRiferimentiCliente.Clear() Catch ex As SqlException Select Case ex.ErrorCode Case -2146232060 Messaggi.Errore(ex.Message, "Attenzione") 'MessageBox.Show("Qualche campo ha un contenuto di lunghezza superiore a quello consentito") mOperazione = TipoOperazione.Nessuna Case Else Messaggi.Errore(ex.Message, "Attenzione") End Select Catch ex As Exception Messaggi.Errore(ex.Message, "Attenzione") End Try End SubIn fase di salvataggio, dopo aver verificato la validità dei dati (DatiValidi) e ottenuto (come già accennato sopra) il codice (NuovoCodice) dell'eventuale nuovo record, nonché dopo aver caricato una riga (come si vedrà nel seguito) si deve seguire una logica differente a seconda che il salvataggio riguardi un cliente nuovo o la modifica di un cliente esistente.
La logica di funzionamento per il nuovo inserimento è simile a quella seguita nelle form a tabella singola, pur gestendo anche il salvataggio dei dati delle griglie nelle tabelle di dettaglio. Quella per la modifica invece è completamente differente: si eliminano tutti i record di dettaglio relativi al cliente e si inseriscono nuovamente. Sarà poi il DataSet a preoccuparsi dell'aggiornamento corretto dei dati nel database.Se ci sono oggetti-dato da inserire, si istanziano, si valorizzano e si aggiungono (AggiungiRigaNuovaDettaglio) nuove DataRows al Dataset. Stavolta, si usa il metodo TryParseToDBNull della classe ValoreCampo, per assicurare la congruità dei dati e il rispetto delle relazioni tra master e dettagli. Se durante il salvataggio delle singole righe sorge un'eccezione, si alza il flag errori e si termina la procedura, avvisando della cosa l'utente.
Private Sub CaricaRiga() Dim rigaNuova As DataRow = Nothing If mOperazione = TipoOperazione.Inserimento Then rigaNuova = Dati.RigaNuovaMaster Else Dati.RigaCorrenteMaster(rigaNuova) End If rigaNuova("Codice") = _ ValoreCampo(Of Integer).TryParseToDBNull(StringToInteger(TxtCodice.Text), Integer.MaxValue) rigaNuova("Nome") = ValoreCampo(Of String).TryParseToDBNull(TxtNome.Text, String.Empty) rigaNuova("Indirizzo") = ValoreCampo(Of String).TryParseToDBNull(TxtInd.Text, String.Empty) rigaNuova("CAP") = ValoreCampo(Of String).TryParseToDBNull(TxtCAP.Text, String.Empty) rigaNuova("Citta") = ValoreCampo(Of String).TryParseToDBNull(TxtCitta.Text, String.Empty) rigaNuova("Provincia") = ValoreCampo(Of String).TryParseToDBNull(TxtProv.Text, String.Empty) rigaNuova("Stato") = ValoreCampo(Of String).TryParseToDBNull(CmbStato.Text, String.Empty) rigaNuova("Telefono") = ValoreCampo(Of String).TryParseToDBNull(TxtTel1.Text, String.Empty) rigaNuova("Fax") = ValoreCampo(Of String).TryParseToDBNull(TxtFax1.Text, String.Empty) rigaNuova("Cellulare") = ValoreCampo(Of String).TryParseToDBNull(TxtCel1.Text, String.Empty) rigaNuova("Telefono1") = ValoreCampo(Of String).TryParseToDBNull(TxtTel2.Text, String.Empty) rigaNuova("Fax1") = ValoreCampo(Of String).TryParseToDBNull(TxtFax2.Text, String.Empty) rigaNuova("Cellulare1") = ValoreCampo(Of String).TryParseToDBNull(TxtCel2.Text, String.Empty) rigaNuova("Codice_fiscale") = ValoreCampo(Of String).TryParseToDBNull(TxtCodFis.Text, String.Empty) rigaNuova("Partita_iva") = ValoreCampo(Of String).TryParseToDBNull(TxtPIVA.Text, String.Empty) rigaNuova("Pagamento") = ValoreCampo(Of String).TryParseToDBNull(CmbPagam.Text, String.Empty) rigaNuova("Banca") = ValoreCampo(Of String).TryParseToDBNull(CmbBanca.Text, String.Empty) rigaNuova("Agenzia") = ValoreCampo(Of String).TryParseToDBNull(TxtAgenzia.Text, String.Empty) rigaNuova("ABI") = ValoreCampo(Of String).TryParseToDBNull(TxtABI.Text, String.Empty) rigaNuova("CAB") = ValoreCampo(Of String).TryParseToDBNull(TxtCAB.Text, String.Empty) rigaNuova("NumCC") = ValoreCampo(Of String).TryParseToDBNull(TxtNumCC.Text, String.Empty) rigaNuova("TitCC") = ValoreCampo(Of String).TryParseToDBNull(TxtTitCC.Text, String.Empty) rigaNuova("CIN") = ValoreCampo(Of String).TryParseToDBNull(TxtCIN.Text, String.Empty) rigaNuova("IBAN") = ValoreCampo(Of String).TryParseToDBNull(TxtIBAN.Text, String.Empty) rigaNuova("Internet") = ValoreCampo(Of String).TryParseToDBNull(TxtInternet.Text, String.Empty) rigaNuova("EMail") = ValoreCampo(Of String).TryParseToDBNull(TxtMail.Text, String.Empty) rigaNuova("Riclis") = _ ValoreCampo(Of Single).TryParseToDBNull(StringToSingle(TxtRicLis.Text), Single.MaxValue) rigaNuova("Oratecs") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOTecSpec.Text), Decimal.MaxValue) rigaNuova("Oratecsstr") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOTecSpecStr.Text), Decimal.MaxValue) rigaNuova("Oratec") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOTec.Text), Decimal.MaxValue) rigaNuova("Oratecstr") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOTecStr.Text), Decimal.MaxValue) rigaNuova("Oraaiu") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOAiu.Text), Decimal.MaxValue) rigaNuova("Oraaiustr") = _ ValoreCampo(Of Decimal).TryParseToDBNull(StringToDecimal(TxtCOAiuStr.Text), Decimal.MaxValue) rigaNuova("Modifica") = False If mOperazione = TipoOperazione.Inserimento Then If Not Dati.AggiungiRigaNuovaMaster(rigaNuova) Then Messaggi.Errore(Dati.DescrizioneErrore, "Errore") Else Dati.LeggiRecordMaster(Dati.NumeroRigheMaster - 1) Dati.TrovaRecord() End If End If End SubIl metodo CaricaRiga richiamato all'inizio di BtnConferma_Click è concettualmente simile a quello per una tabella singola, ma nel popolare la nuova riga ricorre al metodo TryParseToDBNull della classe ValoreCampo.
Private Sub BtnAnnulla_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnAnnulla.Click Dim precOper As TipoOperazione = mOperazione mOperazione = TipoOperazione.Nessuna 'Controllo se si stava inserendo il primo record in assoluto If Dati.NumeroRigheMaster = 0 Then PreparaVuoto() TxtCodice.ReadOnly = False 'Svuoto gli array di inserimento delle nuove righe e modifica delle esistenti per i dettagli mSediCliente.Clear() mRiferimentiCliente.Clear() Exit Sub End If Try 'Tolgo il blocco Dati.ImpostaColonnaModificaMaster(False) If Not Dati.TrovaRecord() Then Messaggi.Avviso("Errore di posizionamento sul record precedentemente visualizzato !", _ "Annulla operazione") Else VisualizzaDati() End If Catch ex As Exception mOperazione = precOper Messaggi.Errore(ex.ToString, "Errore") Exit Sub End Try SbloccaBarra() TbrStrumenti.Select() TxtCodice.ReadOnly = False 'Svuoto gli array di inserimento delle nuove righe e modifica delle esistenti per i dettagli mSediCliente.Clear() mRiferimentiCliente.Clear() End SubNon molto diversa dalla gestione del BtnAnnulla di una form basata su una sola tabella, tranne che nelle ultime due righe, in cui vengono svuotate le due liste di oggetti-dato per prepararle a una successiva compilazione in caso di inserimento o modifica.
Per i pulsanti posti sotto le griglie, che permettono inserimento e modifica e cancellazione agendo sui dettagli esposti nelle griglie stesse, la spiegazione del codice sarà un po' più dettagliata:
Private Sub BtnAggrigaS_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnAggRigaS.Click If mOperazione = TipoOperazione.Nessuna Then Exit SubInnanzitutto se non è in corso alcuna operazione si esce dalla procedura senza fare alcunché, perché nulla deve essere fatto sulle griglie se non in fase di inserimento o modifica di un record cliente.
If Me.TxtCodice.Text.Trim = String.Empty Then Messaggi.Avviso( _ "Impossibile aggiungere nuove sedi prima di avere indicato il codice del cliente !", _ "Attenzione") Exit Sub End IfSi verifica quindi che sia stato valorizzato il codice cliente e in caso contrario si esce dalla routine, in quanto è necessario alle operazioni seguenti. Essendo compilato in automatico dovrebbe essere sempre valorizzato, ma un controllo in più non fa mai male.
Dim rigaNuova As New ClientiSediSi crea una nuova istanza di ClientiSedi per il passaggio delle informazioni necessarie alla form di dialogo.
rigaNuova.Codice = Integer.Parse(Me.TxtCodice.Text)Nel caso di nuovo inserimento l'unica informazione necessaria è il codice del cliente.
Dim frm As New FrmClientiSedi(rigaNuova, TipoOperazione.Inserimento) Dim risposta As DialogResult = frm.ShowDialog()Si crea una nuova istanza della form di inserimento/modifica delle sedi (illustrata nell'articolo precedente), passando al suo costruttore l'istanza di ClientiSedi e il tipo di operazione in corso (inserimento).
Si visualizza la form di dialogo e se ne attende la risposta, anche se, in questo caso, il valore di risposta è forzatamente ininfluente: questo è dovuto al fatto che l'utente, pur avendo magari inserito più di una sede, per uscire dalla form di dialogo deve comunque usare il pulsante di uscita; pertanto risposta riceve sempre un valore Cancel dalla form di dialogo, ma c'è ugualmente modo di controllare se l'utente ha inserito nuove sedi, verificando il numero degli elementi che compongono la lista/proprietà CampiSedi (ricordate? La proprietà dedicata a fornire i valori delle nuove sedi inserite).If frm.CampiSedi.Count > 0 Then For indSedi As Integer = 0 To frm.CampiSedi.Count - 1 AggiungiNuovoElementoASedi( _ ValoreCampo(Of Integer).Value(StringToInteger( _ frm.CampiSedi(indSedi).Codice.ToString), Integer.MaxValue), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).RagSoc, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Ind, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Citta, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Cap, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Prov, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Stato, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Tel, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Fax, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(indSedi).Cel, String.Empty)) Next Else frm = Nothing Exit Sub End If frm = NothingSe ci sono nuove sedi inserite, si scandisce la lista ricevuta e si aggiungono oggetti-dati (AggiungiNuovoElementoASedi), sfruttando nuovamente il metodo Value della classe ValoreCampo.
SvuotaGriglie(GrigliaDaPreparare.Prima) PopolaGriglie(GrigliaDaPreparare.Prima)Infine si aggiorna la griglia delle sedi, prima svuotandola e poi ripopolandola con i dati della lista mSediCliente, che nel frattempo sono cambiati.
Private Sub BtnModrigaS_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnModRigaS.Click If mOperazione = TipoOperazione.Nessuna Then Exit SubAnche nella modifica della riga si verifica che non sia in corso alcuna operazione, ma dopo si prosegue diversamente:
Dim nRiga As Integer = DgvSedi.CurrentRow.Index Dim rigaDaModificare As New ClientiSedi 'Passo i valori della riga da modificare rigaDaModificare.Codice = Convert.ToInt32(DgvSedi.Rows(nRiga).Cells("Codice").Value) rigaDaModificare.RagSoc = DgvSedi.Rows(nRiga).Cells("Ragione Sociale").Value.ToString rigaDaModificare.Ind = DgvSedi.Rows(nRiga).Cells("Indirizzo").Value.ToString rigaDaModificare.Cap = DgvSedi.Rows(nRiga).Cells("CAP").Value.ToString rigaDaModificare.Citta = DgvSedi.Rows(nRiga).Cells("Citta").Value.ToString rigaDaModificare.Prov = DgvSedi.Rows(nRiga).Cells("Prov.").Value.ToString rigaDaModificare.Stato = DgvSedi.Rows(nRiga).Cells("Stato").Value.ToString rigaDaModificare.Tel = DgvSedi.Rows(nRiga).Cells("Telefono").Value.ToString rigaDaModificare.Fax = DgvSedi.Rows(nRiga).Cells("Fax").Value.ToString rigaDaModificare.Cel = DgvSedi.Rows(nRiga).Cells("Cellulare").Value.ToStringSi legge l'indice della riga corrente e si crea una nuova istanza di ClientiSedi, di cui valorizzano le proprietà traendo i valori dalla riga stessa. Questa ClientiSedi verrà passata alla form di dialogo.
Dim frm As New FrmClientiSedi(rigaDaModificare, TipoOperazione.Modifica) Dim risposta As DialogResult = frm.ShowDialog()Anche in questo caso creo una nuova istanza della form di inserimento/modifica delle sedi e passo al suo costruttore l'istanza di ClientiSedi, ma il tipo di operazione in corso è modifica. Stavolta, il valore di risposta è importante e va valutato: se infatti l'utente ha premuto il tasto di uscita, nulla dovrà essere fatto, viceversa i valori attuali della riga della griglia andranno sostituiti da quelli salvati nella lista di oggetti ClientiSedi, che in caso di modifica contiene sempre un solo elemento (quello di indice zero).
If risposta = Windows.Forms.DialogResult.OK Then ModificaElementoSedi(ValoreCampo(Of Integer).Value( _ StringToInteger(frm.CampiSedi(0).Codice.ToString), Integer.MaxValue), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).RagSoc, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Ind, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Citta, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Cap, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Prov, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Stato, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Tel, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Fax, String.Empty), _ ValoreCampo(Of String).Value(frm.CampiSedi(0).Cel, String.Empty))Naturalmente, in uscita dalla procedura si aggiorna la griglia. Anche stavolta si usa il metodo Value di ValoreCampo per tipizzare i parametri, ma questi vengono passati a un metodo diverso:
Private Sub ModificaElementoSedi(ByVal codiceSede As Integer, _ ByVal ragSocSede As String, _ ByVal indSede As String, _ ByVal cittaSede As String, _ Optional ByVal capSede As String = "", _ Optional ByVal provSede As String = "", _ Optional ByVal statoSede As String = "", _ Optional ByVal telSede As String = "", _ Optional ByVal faxSede As String = "", _ Optional ByVal celSede As String = "") If Not mSediCliente.Count > 0 Then Exit Sub 'Cerco il record nell'array For i As Integer = 0 To mSediCliente.Count - 1 If mSediCliente(i).Codice = codiceSede And mSediCliente(i).RagSoc = ragSocSede _ And mSediCliente(i).Citta = cittaSede Then mSediCliente(i).Ind = indSede mSediCliente(i).Cap = capSede mSediCliente(i).Prov = provSede mSediCliente(i).Stato = statoSede mSediCliente(i).Tel = telSede mSediCliente(i).Fax = faxSede mSediCliente(i).Cel = celSede Exit For End If Next i End SubDopo un primo controllo che la lista contenga elementi, si scandisce la lista per trovare l'elemento da modificare e se ne modificano le proprietà.
Private Sub BtnCancrigaS_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnCancRigaS.Click Dim nRiga As Integer = DgvSedi.CurrentRow.Index Dim risposta As DialogResult = Messaggi.SiNo( _ "Sei sicuro/a di volere eliminare la sede con Ragione Sociale " & _ DgvSedi.Rows(nRiga).Cells("Ragione Sociale").Value.ToString & _ " e residente a " & DgvSedi.Rows(nRiga).Cells("Citta").Value.ToString & " ?", _ "Eliminazione Sede") If risposta = Windows.Forms.DialogResult.No Then Exit Sub 'Elimino la riga dall'array mSediCliente.RemoveAt(nRiga) 'Aggiorno i dati nella griglia SvuotaGriglie(GrigliaDaPreparare.Prima) PopolaGriglie(GrigliaDaPreparare.Prima) End SubLa cancellazione della riga, invece, è abbastanza semplice: dopo aver letto l'indice della riga corrente, se ne presentano alcuni valori nella richiesta di conferma della cancellazione. Se si ha la conferma, si usa il metodo RemoveAt della lista e, al solito, si aggiorna la griglia.
In modo analogo si procede per i pulsanti posti sotto la griglia riferimenti, per cui non si ritiene di esporli in questo articolo.
Resta ancora da dire che, in alcuni metodi di convalida, viene sfruttato il metodo Formatta della classe Formattazione del progetto APP.UI per la corretta visualizzazione dei dati.
Conclusione
In questo articolo abbiamo completato la descrizione dello sviluppo della prima form master-details, la FrmClienti.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.