ByRef変数を.net winformsダイアログフォームに永続化するにはどうすればよいですか?
-
02-07-2019 - |
質問
「部門ピッカー」を作成しています。私の「プライマリ」の多くのモーダルポップアップフォームとして機能するフォーム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();