Ricerca…
Migliori pratiche
Un UserForm
è un modulo di classe con un designer e un'istanza predefinita . È possibile accedere al progettista premendo Maiusc + F7 mentre si visualizza il code-behind e si può accedere al code-behind premendo F7 durante la visualizzazione del designer .
Lavora con una nuova istanza ogni volta.
Essendo un modulo di classe , una forma è quindi un progetto per un oggetto . Poiché un modulo può contenere dati e stato, è preferibile lavorare con una nuova istanza della classe, anziché con quella predefinita / globale:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
'...
End If
End With
Invece di:
UserForm1.Show vbModal
If Not UserForm1.IsCancelled Then
'...
End If
Lavorare con l'istanza predefinita può portare a piccoli bug quando il modulo viene chiuso con il pulsante rosso "X" e / o quando Unload Me
viene usato nel code-behind.
Attuare la logica altrove.
Un modulo dovrebbe riguardare solo la presentazione : un pulsante Click
gestore che si collega a un database ed esegue una query parametrizzata basata sull'input dell'utente, sta facendo troppe cose .
Invece, implementare la logica applicativa nel codice che è responsabile per la visualizzazione del modulo, o anche meglio, in moduli e procedure dedicate.
Scrivi il codice in modo tale che UserForm sia sempre e solo responsabile di sapere come visualizzare e raccogliere i dati: da dove provengono i dati, o che cosa succede successivamente ai dati, non ne preoccupa.
Il chiamante non dovrebbe essere disturbato dai controlli.
Crea un modello ben definito per il modulo con cui lavorare, nel proprio modulo di classe dedicato o incapsulato all'interno del codice stesso del modulo stesso - esporre il modello con le procedure Property Get
e far lavorare il codice client con questi: questo rende la forma un'astrazione sui controlli e i loro dettagli nitty-grintosi, che espongono solo i dati rilevanti al codice cliente.
Questo significa codice che assomiglia a questo:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .Message, vbInformation
End If
End With
Invece di questo:
With New UserForm1
.Show vbModal
If Not .IsCancelled Then
MsgBox .txtMessage.Text, vbInformation
End If
End With
Gestire l'evento QueryClose.
I moduli hanno in genere un pulsante Chiudi e le finestre di dialogo / prompt hanno pulsanti Ok e Annulla ; l'utente può chiudere il modulo utilizzando la casella di controllo del modulo (il pulsante rosso "X"), che distrugge l'istanza del modulo per impostazione predefinita (un'altra buona ragione per lavorare ogni volta con una nuova istanza ).
With New UserForm1
.Show vbModal
If Not .IsCancelled Then 'if QueryClose isn't handled, this can raise a runtime error.
'...
End With
End With
Il modo più semplice per gestire l'evento QueryClose
è impostare il parametro Cancel
su True
e quindi nascondere il modulo anziché chiuderlo :
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Me.Hide
End Sub
In questo modo il pulsante "X" non distruggerà mai l'istanza e il chiamante può accedere in sicurezza a tutti i membri pubblici.
Nascondi, non chiudere.
Il codice che crea un oggetto dovrebbe essere responsabile della sua distruzione: non è responsabilità del modulo scaricare e terminare se stesso.
Evita l'uso di Unload Me
nel code-behind di un modulo. Chiama invece. Me.Hide
, in modo che il codice chiamante possa ancora utilizzare l'oggetto creato al momento della chiusura del modulo.
Nome cose.
Utilizzare la finestra degli strumenti Proprietà ( F4 ) per assegnare un nome a ciascun controllo su un modulo. Il nome di un controllo viene utilizzato nel code-behind, quindi a meno che non si stia utilizzando uno strumento di refactoring in grado di gestirlo, rinominare un controllo interromperà il codice , quindi è molto più facile fare le cose in modo corretto in primo luogo, piuttosto che provare per scoprire esattamente quale delle 20 caselle di testo TextBox12
rappresenta.
Tradizionalmente, i controlli UserForm sono denominati con prefissi in stile ungherese:
-
lblUserName
per un controlloLabel
che indica un nome utente. -
txtUserName
per un controlloTextBox
cui l'utente può immettere un nome utente. -
cboUserName
per un controlloComboBox
cui l'utente può immettere o selezionare un nome utente. -
lstUserName
per un controlloListBox
cui l'utente può selezionare un nome utente. -
btnOk
ocmdOk
per un controlloButton
etichettato "Ok".
Il problema è che quando ad esempio l'interfaccia utente viene ridisegnata e un ComboBox
trasforma in un ListBox
, il nome deve cambiare per riflettere il nuovo tipo di controllo: è meglio nominare i controlli per quello che rappresentano, piuttosto che dopo il loro tipo di controllo - per disaccoppiare il controllo codice dall'interfaccia utente il più possibile.
-
UserNameLabel
per un'etichetta di sola lettura che indica un nome utente. -
UserNameInput
per un controllo in cui l'utente può immettere o selezionare un nome utente. -
OkButton
per un pulsante di comando con l'etichetta "Ok".
Qualunque sia lo stile scelto, tutto è meglio che lasciare a tutti i controlli i loro nomi predefiniti. Anche la coerenza nello stile dei nomi è ideale.
Gestione di QueryClose
L'evento QueryClose
viene generato ogni volta che un modulo sta per essere chiuso, sia tramite azione dell'utente che a livello di programmazione. Il parametro CloseMode
contiene un valore enum VbQueryClose
che indica come è stato chiuso il modulo:
Costante | Descrizione | Valore |
---|---|---|
vbFormControlMenu | Il modulo si sta chiudendo in risposta all'azione dell'utente | 0 |
vbFormCode | Il modulo si sta chiudendo in risposta a un'istruzione Unload | 1 |
vbAppWindows | La sessione di Windows sta finendo | 2 |
vbAppTaskManager | Task Manager di Windows sta chiudendo l'applicazione host | 3 |
vbFormMDIForm | Non supportato in VBA | 4 |
Per una migliore leggibilità, è preferibile utilizzare queste costanti anziché utilizzare direttamente il loro valore.
Un form utente cancellabile
Dato un modulo con un pulsante Annulla
Il code-behind del modulo potrebbe assomigliare a questo:
Option Explicit
Private Type TView
IsCancelled As Boolean
SomeOtherSetting As Boolean
'other properties skipped for brievety
End Type
Private this As TView
Public Property Get IsCancelled() As Boolean
IsCancelled = this.IsCancelled
End Property
Public Property Get SomeOtherSetting() As Boolean
SomeOtherSetting = this.SomeOtherSetting
End Property
'...more properties...
Private Sub SomeOtherSettingInput_Change()
this.SomeOtherSetting = CBool(SomeOtherSettingInput.Value)
End Sub
Private Sub OkButton_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
this.IsCancelled = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
this.IsCancelled = True
Me.Hide
End If
End Sub
Il codice chiamante potrebbe quindi visualizzare il modulo e sapere se è stato cancellato:
Public Sub DoSomething()
With New UserForm1
.Show vbModal
If .IsCancelled Then Exit Sub
If .SomeOtherSetting Then
'setting is enabled
Else
'setting is disabled
End If
End With
End Sub
La proprietà IsCancelled
restituisce True
quando si fa clic sul pulsante Annulla o quando l'utente chiude il modulo utilizzando la casella di controllo .