Как мне сохранить переменную ByRef в диалоговой форме .net winforms?

StackOverflow https://stackoverflow.com/questions/150010

Вопрос

Я создаю форму "выбор отдела", которая будет служить модальной всплывающей формой со многими моими "основными" формами приложения 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();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top