Pregunta

Estoy creando un " selector de departamento " formulario que va a servir como un formulario emergente modal con muchos de mis '' primarios '' formas de una aplicación Winforms. Idealmente, el usuario va a hacer clic en un ícono al lado de un cuadro de texto que aparecerá en el formulario, seleccionará el departamento que necesita, y cuando haga clic en Aceptar, el cuadro de diálogo se cerrará y tendré el valor seleccionado para mí. actualizar el cuadro de texto con.

Ya hice la ruta pasando al propietario del cuadro de diálogo al formulario de diálogo y haciendo que el evento de clic del botón Aceptar haga la actualización adecuada, pero esto me obliga a hacer un DirectCast para el tipo de formulario y luego puedo solo reutilice el selector en el formulario actual.

He podido usar una variable ByRef en el constructor y actualizar con éxito un valor, pero solo funciona en el constructor. Si intento asignar el valor ByRef a alguna variable interna en la clase Selector de departamento, pierdo el aspecto de referencia. Este es mi código básico adjunto a mi formulario:

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

¿Alguien puede decirme lo que me falta aquí o un enfoque diferente para que esto suceda?

Nota: El ejemplo de código está en VB.NET, pero también tomaré las respuestas de C #. 8 ^ D

¿Fue útil?

Solución

En tales casos, generalmente o bien

  • Escribir una función ShowDialog que haga lo que quiero (por ejemplo, devolver el valor) o
  • Simplemente deje que el resultado sea una propiedad en el diálogo. Así es como lo hacen los cuadros de diálogo de archivos comunes en el BCL. La persona que llama debe leer la propiedad para obtener el resultado. Eso está bien en mi opinión.

También puede combinar estos métodos, haciendo que el valor del resultado sea una propiedad en el cuadro de diálogo y creando un método ShowDialog que devuelva ese valor de propiedad, ya sea como ByRef como desee o como un valor de retorno, según sus necesidades.

Agregaré esto como una instrucción de uso, por ejemplo (lo siento, no hay VB aquí, y dijiste que C # es bienvenido):

using (var dlg = new DeptPicker()) {
    if (dlg.ShowDialog() == DialogResult.OK) {
        myTextBoxOrWhatEver.Text = dlg.TargetResult;
    }
}

En el cuadro de diálogo, simplemente haga esto:

void okButton_Click(object sender, EventArgs e)
{
    TargetResult = whatever; // can also do this when the selection changes
    DialogResult = DialogResult.OK;
    Close();
}

Sin embargo, no utilicé la nueva implementación ShowDialog en este ejemplo.

Otros consejos

El problema es que asignar TargetResult en el constructor está utilizando la cadena como referencia. La cadena m_TargetResult es solo una copia de la cadena de referencia, no una referencia a la cadena original.

En cuanto a cómo hacer un "puntero" al original, no lo sé.

Esto se hace aún más difícil por el hecho de que VB.NET no admite bloques de código inseguros, por lo que no puede hacer una referencia de puntero a la cadena.

Puede pasar la referencia del cuadro de texto al formulario modal.

Deje que el usuario elija cualquier departamento. Cuando el usuario hace clic en Aceptar, establezca la propiedad de texto del cuadro de texto referido en el texto o id del departamento elegido (depende de lo que necesite)

Estoy usando el código provisto por usted.


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: no he probado esto. Espero que te hagas una idea de lo que quiero decir.

OregonGhost: ¿Esto se ve mejor?

El usuario puede llamar al nuevo DeptPicker (). GetSelectedDepartment (). No sabía que no necesitaba publicar la respuesta nuevamente & amp; podría usar la misma publicación.

Gracias OregonGhost. Ahora, ¿se ve bien?

Esto puede funcionar:

    // 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();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top