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

È stato utile?

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();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top