¿Cómo persisto una variable ByRef en el formulario de diálogo .net winforms?
-
02-07-2019 - |
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
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();