ByRef変数を.net winformsダイアログフォームに永続化するにはどうすればよいですか?

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

質問

「部門ピッカー」を作成しています。私の「プライマリ」の多くのモーダルポップアップフォームとして機能するフォームWinformsアプリケーションのフォーム。理想的には、ユーザーはフォームをポップアップするテキストボックスの横にあるアイコンをクリックし、必要な部門を選択し、[OK]をクリックするとダイアログが閉じて、値が選択されますでテキストボックスを更新します。

ダイアログボックスの所有者をダイアログフォームに渡し、[OK]ボタンのクリックイベントで適切な更新を行うルートを既に実行しましたが、これにより、フォームタイプにDirectCastを実行するように強制されます。現在のフォームでのみピッカーを再利用します。

コンストラクターでByRef変数を使用して値を正常に更新できましたが、コンストラクターでのみ機能します。 Department Pickerクラスの内部変数にByRef値を割り当てようとすると、その参照側面が失われます。これはフォームに添付された基本的なコードです。

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で共通ファイルダイアログが行う方法です。呼び出し元は、プロパティを読み取って結果を取得する必要があります。私の意見では大丈夫です。

これらのメソッドを組み合わせて、ダイアログの結果値をプロパティにし、必要に応じてByRefまたは戻り値としてそのプロパティ値を返すShowDialogメソッドを作成することもできます。

たとえば、これを使用方法の説明として追加します(申し訳ありませんが、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が安全でないコードブロックをサポートしていないため、文字列へのポインター参照を作成できないため、さらに難しくなります。

テキストボックスの参照をモーダルフォームに渡すことができます。

ユーザーに部門を選択させます。ユーザーが[OK]をクリックしたら、参照されたテキストボックスのテキストプロパティを選択した部門のテキストまたは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

注:これはテストしていません。あなたが私が何を意味するのか理解していただければ幸いです。

OregonGhost:これは見栄えがよいですか

ユーザーは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