【问题标题】:How do I persist a ByRef variable into .net winforms dialog form?如何将 ByRef 变量保存到 .net winforms 对话框表单中?
【发布时间】:2008-09-29 18:29:09
【问题描述】:

我正在创建一个“部门选择器”表单,该表单将用作模式弹出表单,其中包含我的许多 Winforms 应用程序的“主要”表单。理想情况下,用户将单击将弹出表单的文本框旁边的图标,他们将选择所需的部门,当他们单击确定时,对话框将关闭,我将为我选择值更新文本框。

我已经完成了将对话框的所有者传递到对话框表单并让 OK 按钮单击事件进行正确更新的路线,但这迫使我对表单类型进行 DirectCast,然后我可以仅在当前表单上重用选择器。

我已经能够在构造函数中使用 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

【问题讨论】:

    标签: .net winforms reference modal-dialog


    【解决方案1】:

    在这种情况下,我通常要么

    • 编写一个 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 实现。

    【讨论】:

    • 现在我表现出我的无知。如何让 ShowDialog 方法返回除对话框结果枚举(如 OK、Cancel 等)以外的值?
    • 将您的 m_TargetResult 公开为部门选择器表单中的属性。然后,当用户单击“确定”时,隐藏()而不是关闭()您的选择器表单。然后可以得到:x = DepartmentPickerForm.TargetResult。最后,在您访问完所有您需要的内容后关闭表单。
    • 您需要发布最后一条评论作为答案。我认为这会奏效,我想正确标记它,这样人们就可以在不深入研究 cmets 的情况下阅读它。
    • 你不需要隐藏对话框,关闭就足够了。请确保在处置表单时不要处置该属性,因为这是在关闭期间发生的情况。
    • 看看我添加的例子。这就是我在上一个应用程序中几次这样做的方式,以及打开文件对话框等的工作方式。
    【解决方案2】:

    问题是在构造函数中分配 TargetResult 是使用字符串作为引用。 m_TargetResult 字符串只是 ref 字符串的副本,而不是对原始字符串的引用。

    至于如何给原文做一个“指针”,我不知道。

    由于 VB.NET 不支持不安全的代码块,因此您无法对字符串进行指针引用,这一事实使这变得更加困难。

    【讨论】:

      【解决方案3】:

      您可以将文本框引用传递给模态表单。

      让用户选择任何部门。当用户单击确定时,将引用文本框的文本属性设置为所选部门的文本或 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

      【讨论】:

      • 将对话框与调用者紧密结合。我不建议这样做。
      【解决方案4】:
      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

      注意:我没有对此进行测试。我希望你明白我的意思。

      OregonGhost:这样看起来更好吗?

      用户可以调用new DeptPicker().GetSelectedDepartment()。 我不知道我不需要再次发布答案并且可以使用相同的帖子。

      感谢 OregonGhost。现在,看起来还好吗?

      【讨论】:

      • 是的,虽然这个例子没有抓住重点,因为它省略了如何从对话框获取结果值到函数的非常重要的部分:)
      • 哦,你知道你可以编辑你的第一个帖子,而不是发布一个新的,对吗?
      【解决方案5】:

      这可能有效:

          // 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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 2010-12-06
        • 1970-01-01
        相关资源
        最近更新 更多