3

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

4

5 に答える 5

4

そのような場合、私は通常、

  • 私が望むことをする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 実装を使用しませんでした。

于 2008-09-29T18:34:22.617 に答える
0

これはうまくいくかもしれません:

    // 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();
于 2008-09-30T18:44:49.057 に答える
0

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() を呼び出すことができます。回答を再度投稿する必要がなく、同じ投稿を使用できることを知りませんでした。

ありがとうオレゴンゴースト。さて、見た目は大丈夫ですか?

于 2008-09-29T21:11:09.790 に答える
0

問題は、コンストラクターで TargetResult を割り当てると、文字列が参照として使用されることです。m_TargetResult 文字列は、元の文字列への参照ではなく、ref 文字列の単なるコピーです。

オリジナルへの「ポインター」を作成する方法については、わかりません。

これは、VB.NET が安全でないコード ブロックをサポートしていないため、文字列へのポインター参照を作成できないため、さらに困難になります。

于 2008-09-29T18:35:32.427 に答える
0

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

ユーザーが任意の部門を選択できるようにします。ユーザーが [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

于 2008-09-29T19:16:34.277 に答える