Comment conserver une variable ByRef dans un formulaire de dialogue .net winforms?
-
02-07-2019 - |
Question
Je crée un "sélecteur de département". formulaire qui va servir de formulaire contextuel modal avec bon nombre de mes "primaires" formes d'une application Winforms. Idéalement, l'utilisateur va cliquer sur une icône en regard d'une zone de texte qui fera apparaître le formulaire, il sélectionnera le service dont il a besoin et, lorsqu'il cliquera sur OK, la boîte de dialogue se fermera et la valeur sélectionnée pour moi mettre à jour la zone de texte avec.
J'ai déjà fait la route en passant le propriétaire de la boîte de dialogue dans le formulaire de dialogue et en faisant en sorte que l'événement de clic du bouton OK effectue la mise à jour appropriée, mais cela m'oblige à faire un DirectCast pour le type de formulaire et je peux alors réutilisez uniquement le sélecteur sur le formulaire actuel.
J'ai pu utiliser une variable ByRef dans le constructeur et mettre à jour une valeur, mais cela ne fonctionne que dans le constructeur. Si j'essaie d'attribuer la valeur ByRef à une variable interne de la classe Sélecteur de département, je perds son aspect de référence. Ceci est mon code de base attaché à mon formulaire:
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
Quelqu'un peut-il me dire ce qui me manque ou une approche différente pour y arriver?
Remarque: l'exemple de code est dans VB.NET, mais je vais aussi prendre toutes les réponses C #. 8 ^ D
La solution
Dans de tels cas, je généralement
- Ecrivez une fonction ShowDialog qui fait ce que je veux (par exemple, renvoyer la valeur) ou
- Laissez le résultat être une propriété dans la boîte de dialogue. Voici comment les dialogues de fichiers courants le font dans la BCL. L'appelant doit ensuite lire la propriété pour obtenir le résultat. C'est bien à mon avis.
Vous pouvez également combiner ces méthodes en faisant de la valeur du résultat une propriété dans la boîte de dialogue et en créant une méthode ShowDialog qui renvoie cette valeur de propriété, sous la forme ByRef à votre guise ou en tant que valeur de retour, en fonction de vos besoins.
Je vais ajouter ceci en tant qu'instruction d'utilisation, par exemple (désolé, aucun VB ici et vous avez dit que C # était le bienvenu):
using (var dlg = new DeptPicker()) {
if (dlg.ShowDialog() == DialogResult.OK) {
myTextBoxOrWhatEver.Text = dlg.TargetResult;
}
}
Dans la boîte de dialogue elle-même, procédez comme suit:
void okButton_Click(object sender, EventArgs e)
{
TargetResult = whatever; // can also do this when the selection changes
DialogResult = DialogResult.OK;
Close();
}
Je n'ai cependant pas utilisé la nouvelle implémentation de ShowDialog dans cet exemple.
Autres conseils
Le problème est que l’attribution de TargetResult au constructeur utilise la chaîne comme référence. La chaîne m_TargetResult est simplement une copie de la chaîne de référence, pas une référence à la chaîne d'origine.
Pour savoir comment créer un " pointeur " à l'original, je ne sais pas.
Cela est rendu encore plus difficile par le fait que VB.NET ne prend pas en charge les blocs de code non sécurisés, vous ne pouvez donc pas faire de référence de pointeur à la chaîne.
Vous pouvez transmettre la référence de la zone de texte au formulaire modal.
Laisser l'utilisateur choisir n'importe quel département. Lorsque l'utilisateur clique sur OK, définissez la propriété text de la zone de texte référencée sur le texte ou l'ID du service choisi (selon vos besoins)
J'utilise le code fourni par vous.
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
Remarque: je n'ai pas testé cela. J'espère que vous avez une idée de ce que je veux dire.
OregonGhost: Est-ce que cela a l'air mieux?
L'utilisateur peut appeler new DeptPicker (). GetSelectedDepartment (). Je ne savais pas que je n'avais plus besoin de poster la réponse & amp; pourrait utiliser le même message.
Merci, OregonGhost. Maintenant, ça vous va?
Cela peut fonctionner:
// 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();