Как мне сохранить переменную ByRef в диалоговой форме .net winforms?
-
02-07-2019 - |
Вопрос
Я создаю форму "выбор отдела", которая будет служить модальной всплывающей формой со многими моими "основными" формами приложения Winforms.В идеале пользователь собирается нажать на значок рядом с текстовым полем, в котором появится форма, он выберет нужный ему отдел, и когда он нажмет "ОК", диалоговое окно закроется, и у меня будет выбрано значение для обновления текстового поля.
Я уже выполнил маршрут с передачей владельца диалогового окна в диалоговую форму и с тем, чтобы событие нажатия кнопки OK выполнило надлежащее обновление, но это вынуждает меня выполнять перенаправление к типу формы, и тогда я могу повторно использовать средство выбора только в текущей форме.
Мне удалось использовать переменную ByRef в конструкторе и успешно обновить значение, но это работает только в конструкторе.Если я попытаюсь присвоить значение ByRef какой-либо внутренней переменной в классе Department Picker, я потеряю его ссылочный аспект.Это мой базовый код, прикрепленный к моей форме:
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
Кто-нибудь может сказать мне, чего мне здесь не хватает, или другой подход, чтобы это произошло?
Примечание:Пример кода приведен в VB.NET, но я также приму любые ответы на C #.8^D
Решение
В таких случаях я обычно либо
- Напишите функцию ShowDialog, которая делает то, что я хочу (напримервозвращает значение) или
- Просто пусть результатом будет свойство в диалоговом окне.Вот как это делают обычные диалоговые окна с файлами в BCL.Затем вызывающий должен прочитать свойство, чтобы получить результат.На мой взгляд, это прекрасно.
Вы также можете объединить эти методы, сделав результирующее значение свойством в диалоговом окне и создав метод ShowDialog, который возвращает значение этого свойства либо в виде ByRef, как вы хотите, либо в виде возвращаемого значения, в зависимости от ваших потребностей.
Я добавлю это в качестве инструкции по использованию, например (извините, здесь нет VB, а вы сказали, что C # приветствуется):
using (var dlg = new DeptPicker()) {
if (dlg.ShowDialog() == DialogResult.OK) {
myTextBoxOrWhatEver.Text = dlg.TargetResult;
}
}
В самом диалоговом окне просто сделайте это:
void okButton_Click(object sender, EventArgs e)
{
TargetResult = whatever; // can also do this when the selection changes
DialogResult = DialogResult.OK;
Close();
}
Однако я не использовал новую реализацию ShowDialog в этом примере.
Другие советы
Проблема в том, что при назначении TargetResult в конструкторе используется строка в качестве ссылки.Строка m_TargetResult - это просто копия строки ref, а не ссылка на исходную строку.
Что касается того, как сделать "указатель" на оригинал, я не знаю.
Это становится еще сложнее из-за того факта, что VB.NET не поддерживает небезопасные блоки кода, поэтому вы не можете создать ссылку указателя на строку.
Вы могли бы передать ссылку на текстовое поле в модальную форму.
Позвольте пользователю выбрать любой отдел.Когда пользователь нажимает кнопку "ОК", установите для свойства text указанного текстового поля значение text или id выбранного отдела (зависит от того, что вам нужно).
Я использую предоставленный вами код.
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
Примечание:Я еще не проверял это.Я надеюсь, вы понимаете, что я имею в виду.
Орегонгост:Это выглядит лучше?
Пользователь может вызвать new DeptPicker().GetSelectedDepartment() .Я не знал, что мне не нужно публиковать ответ снова и я мог бы использовать тот же пост.
Спасибо OregonGhost.Итак, все выглядит нормально?
Это может сработать:
// 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();