Come posso mantenere una variabile ByRef nel modulo di dialogo winforms .net?
-
02-07-2019 - |
Domanda
Sto creando un " selezione di reparto " modulo che fungerà da modulo popup modale con molti dei miei "primari" forme di un'applicazione Winforms. Idealmente, l'utente farà clic su un'icona accanto a una casella di testo che farà apparire il modulo, selezionerà il reparto di cui ha bisogno e quando farà clic su OK, la finestra di dialogo si chiuderà e avrò il valore selezionato per me aggiorna la casella di testo con.
Ho già fatto il percorso passando il proprietario della finestra di dialogo nel modulo di dialogo e facendo in modo che l'evento OK clic sul pulsante esegua l'aggiornamento corretto, ma questo mi costringe a fare un DirectCast al tipo di modulo e quindi posso riutilizzare il selettore solo nel modulo corrente.
Sono stato in grado di utilizzare una variabile ByRef nel costruttore e aggiornare correttamente un valore, ma funziona solo nel costruttore. Se provo ad assegnare il valore ByRef ad una variabile interna nella classe Selezione reparto, perdo l'aspetto di riferimento di esso. Questo è il mio codice di base allegato al mio modulo:
Public Class DeptPicker
Private m_TargetResult As String
Public Sub New(ByRef TargetResult As String)
InitializeComponent()
' This works just fine, my "parent" form has the reference value properly updated.
TargetResult = "Booyah!"
' Once I leave the constructor, m_TargetResult is a simple string value that won't update the parent
m_TargetResult = TargetResult
End Sub
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
DialogResult = Windows.Forms.DialogResult.OK
' I get no love here. m_TargetResult is just a string and doesn't push the value back to the referenced variable I want.
m_TargetResult = "That department I selected."
Me.Close()
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
DialogResult = Windows.Forms.DialogResult.Cancel
Me.Close()
End Sub
End Class
Qualcuno può dirmi cosa mi sto perdendo qui o un approccio diverso per far sì che ciò accada?
Nota: l'esempio di codice è in VB.NET, ma prenderò anche tutte le risposte C #. 8 ^ D
Soluzione
In questi casi, di solito o
- Scrivi una funzione ShowDialog che fa quello che voglio (ad es. restituisci il valore) o
- Lascia che il risultato sia una proprietà nella finestra di dialogo. Ecco come funzionano le finestre di dialogo dei file comuni nel BCL. Il chiamante deve quindi leggere la proprietà per ottenere il risultato. Va bene secondo me.
Puoi anche combinare questi metodi, rendendo il valore del risultato una proprietà nella finestra di dialogo e creando un metodo ShowDialog che restituisce quel valore della proprietà, come ByRef come desideri o come valore di ritorno, a seconda delle tue esigenze.
Aggiungerò questo come istruzione d'uso, ad esempio (scusate, nessun VB qui, e avete detto che C # è il benvenuto):
using (var dlg = new DeptPicker()) {
if (dlg.ShowDialog() == DialogResult.OK) {
myTextBoxOrWhatEver.Text = dlg.TargetResult;
}
}
Nella stessa finestra di dialogo, basta fare questo:
void okButton_Click(object sender, EventArgs e)
{
TargetResult = whatever; // can also do this when the selection changes
DialogResult = DialogResult.OK;
Close();
}
Non ho usato la nuova implementazione ShowDialog in questo esempio.
Altri suggerimenti
Il problema è che l'assegnazione di TargetResult nel costruttore utilizza la stringa come riferimento. La stringa m_TargetResult è solo una copia della stringa ref, non un riferimento alla stringa originale.
Per quanto riguarda come creare un " pointer " all'originale, non lo so.
Ciò è reso ancora più difficile dal fatto che VB.NET non supporta blocchi di codice non sicuri, quindi non è possibile fare un riferimento puntatore alla stringa.
È possibile passare il riferimento alla casella di testo al modulo modale.
Consenti all'utente di scegliere qualsiasi reparto. Quando l'utente fa clic su OK, imposta la proprietà text della casella di testo di riferimento sul testo o sull'ID del dipartimento scelto (dipende da ciò di cui hai bisogno)
Sto usando il codice fornito da te.
Public Class DeptPicker
Private m_TargetTextBox As TextBox
Public Sub New(ByRef TargetTextBox As TextBox)
InitializeComponent()
m_TargetTextBox = TargetTextBox
End Sub
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
DialogResult = Windows.Forms.DialogResult.OK
' I get no love here. m_TargetResult is just a string and doesn't push the value back to the referenced variable I want.
m_TargetTextBox.Text = "That department I selected."
Me.Close()
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
DialogResult = Windows.Forms.DialogResult.Cancel
Me.Close()
End Sub
End Class
Public Class DeptPicker
dim dlgResult as DialogResult
Public Function GetSelectedDepartment() As String
Me.Show vbModal
If (dlgResult = Windows.Forms.DialogResult.OK) Then
return "selected department string here"
Else
return "sorry, you didnt canceled on the form"
End If
End Function
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
dlgResult = Windows.Forms.DialogResult.OK
Me.Close()
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
dlgResult = Windows.Forms.DialogResult.Cancel
Me.Close()
End Sub
End Class
Nota: non l'ho provato. Spero che tu abbia idea di cosa intendo.
OregonGhost: sembra migliore?
L'utente può chiamare il nuovo DeptPicker (). GetSelectedDepartment (). Non sapevo che non avrei bisogno di pubblicare di nuovo la risposta & amp; potrebbe usare lo stesso post.
Grazie OregonGhost. Ora, sembra ok?
Potrebbe funzionare:
// This code in your dialog form. Hide the base showdialog method
// and implement your own versions
public new string ShowDialog() {
return this.ShowDialog(null);
}
public new string ShowDialog(IWin32Window owner) {
// Call the base implementation of show dialog
base.ShowDialog(owner);
// You get here after the close button is clicked and the form is hidden. Capture the data you want.
string s = this.someControl.Text;
// Now really close the form and return the value
this.Close();
return s;
}
// On close, just hide. Close in the show dialog method
private void closeButton_Click(object sender, EventArgs e) {
this.Hide();
}
// This code in your calling form
MyCustomForm f = new MyCustomForm();
string myAnswer = f.ShowDialog();