人生最悪の忘れ物

C#で動的にコントロールを取得するにはどのようにしたらよいのでしょうか?

C#2008ですが、Form1にTextBoxが30個あって、textBox1~textBox30という名前がついています。
このテキストボックスの値をForm2で取得したいのですがなかなかうまくいきません。

-------------------------
Form2:
private void Form2_Click(object sender, EventArgs e){
 Form1 fm = new Form1();
 
 int No = 15; //ここを1~30まで動的にしたい
 string result = fm.textBox15.Text; //直接comboBox_type15と書くのではなく「"comboBox_type" + No.ToString()」のようにしたい
 MessageBox.Show(result);
}
-------------------------

コントロールを配列にして

Control[] ctlArray = new Control[30] { fm.textBox1, fm.textBox2, …, fm.textBox30 };

のようにしてみましたが、エラーになってしまいます。
いろいろネットで検索してみたのですが、「コントロール名を動的に文字列で作成して使う」という方法がどこにも載っていなく、数時間格闘しています。
すみませんがご教授願います。よろしくお願いいたします。

A 回答 (5件)

どう回答したものかとかなり悩みました。


いろいろな考え方があるので。。。

コンストラクタのオーバーロードで自分自分を渡すという
suffreさんの方法もなるほどーと思いました。
「あり」だと思います。

他に方法がいくつかあります。
2つだけ紹介します。

ひとつは、
fm.ShowDialog(this);
と、Owner指定なるものを使って、自分を渡す方法です。
これが一番楽かな、と思っています。
渡されたForm2の方では、
this.OwnerをForm1でキャストすれば、
suffreさんの方法と同じようにForm1のPublicのメンバに
アクセスできます。
例えば、
((Form1)this.Owner).textBox3.Text = "hoge";
です。
オーバーロードとか書かなくていいのでその点簡単でしょう。

もう一つは、Form2の側にPublicなメンバ(特にプロパティ)を
設けて、それを通じてやり取りする、という方法です。
Form1の側では、
Form2 fm2 = new Form2();
としたあと、
fm2.xxx = ・・・
で必要な情報を相手に渡し、
textBox3.Text = fm2.yyy;
というように情報を受け取ります。

DialogResultの値は見ないのでしょうか?
もし見て、それがOKの場合のみ、Form2の側で設定された値を
使いたいという場合、以下のようになるはずです。

if (fm2.ShowDialog(this)== DialogResult.OK) {
textBox3.Text = fm2.yyy;
}

もちろん、初めの方法でも、予めForm1の側で変更される可能性の
あるメンバをバックアップしておいて、Cancelだったらそれを使って
元に戻すということもできますが。。。

。。。

初めの方法を嫌がる人は(おそらくたくさん)います。
・Form2の側にForm1という文字を書かなくてはならない
 → 子は親に依存させたくない
・Form1の側でForm2でForm1の値変更の管理ができない
などという理由からです。
後者の方法ならば、
・Form2の側にForm1という文字を書かないで済む
・最終的に、Form2側で入れた値を使うかどうかがForm1側で分かる
からです。

丸岡孝司著「絶対現場主義 Visual C#実践講座」では、前者の方法について、
以下のように書かれています。
http://www.amazon.co.jp/%E7%B5%B6%E5%AF%BE%E7%8F …
----------------------------
サブフォーム側では、「Owner」プロパティを呼び出し元画面の型でキャストすれば、
そのプロパティを「えへへ。参照し放題ですぜ」というわけだ。
さらに、フォームに乗せてあるコントロールのModifiersプロパティを
Publicなんぞにした日にゃあなた、こりゃタマリませんなあということになる。
いかがだろうか。実際問題、荒業も程があるのであって、決してこの方法を
選択してはならないぞ。
----------------------------

。。。

といいつつ、自分の趣味プログラムでは、
楽なので前者の方法ばかりを使っています。。。
    • good
    • 0
この回答へのお礼

いろいろと詳しくありがとうございます。
お礼を書いている時点でそのすべてを確かめているわけではありませんがとても参考になります。
いろいろな方法があって、その弊害というものは自分が書いているプログラムの中ではまだ
見つけることができていませんから、実体験しないと「理解する」のがなかなか難しいです。

私も趣味でC#をやっていますので現場のようなシビアな環境ではありませんが、紹介してくださった
本も確認してみたいと思います。
今回はわからないことに親切に回答してくださって助かりました。
おそらく、再び他の不明なことで質問すると思います。いちおう質問前にネットで調べてから質問していますが、理解が足りない点はご容赦ください。

どうもありがとうございました。

お礼日時:2010/10/26 01:16

ANo.3です。



えーと、Form1はどのようにして表示しましたか?

「Form2のコード上で」
Form1 fm = new Form1();
とご自身で書かれていますよね。

ということは、"この新しい" Form1 は、当初の段階では
表示されていませんよね。

その後、Fomr1を、
fm.Show();

fm.ShowDialog();
で表示されたということでしょうか。

であるならば、その"新しいForm1"のtextBoxには、
表示前後に関わらず、
((TextBox)fm.Controls["textBox" + No.ToString()]).Text = "hoge";
で、値が入るはずですが、、、

。。。

ちょっと確認したいのですが、おっしゃっているForm1というのは、
本当に今作成たばかりのForm1(のインスタンス)である「fm」でしょうか。
もしかして、書かれているForm2のコードが実行される前から表示されている、
もともとあるForm1ということはないですか?

だとすると、新たに作成したfmに対していくら設定しても
意味がないですよね?

> この方法で値を取ることができましたが、

これで取った値というのは、コードで何も処理していなければ。
Form1の各textBoxに入っている初期値のはずです。
    • good
    • 0
この回答へのお礼

ああ…なんとなくおっしゃっていることがわかりました。

>もしかして、書かれているForm2のコードが実行される前から表示されている、
>もともとあるForm1ということはないですか?

すみませんそのとおりです。Form2表示前にある元のForm1のtextBox1に対して値を入力させたいのです。
そうするとForm1 fm = new Form1();というのはダメですよね…。

以下の方法でできるようになりましたが正しいでしょうか?

Form1:-------------------------
private void Form2_Open(object sender, EventArgs e){
 Form2 fromItem = new Form2(this);
 DialogResult deRet = fromItem.ShowDialog();
}

Form2:-------------------------
public partial class Form2 : Form
{
 Form pFm;
 
 public Form2(Form1 fm){
  pFm = fm;
 }

 private void button_Click(object sender, EventArgs e){
  int no = 1; //例として1とする
  ((TextBox)pFm.Controls["textBox" + no.ToString()]).Text = "hoge";
 }
}

お礼日時:2010/10/25 19:30

ANo2ですが訂正を。



Noのところ、No.ToString() の方が良いですね。

string result = ((TextBox)fm.Controls["textBox" + No.ToString()]).Text;

忘れてたので、念のため。
    • good
    • 0
この回答へのお礼

ありがとうございます。

string result = ((TextBox)fm.Controls["textBox" + No.ToString()]).Text;

この方法で値を取ることができましたが、逆にForm2からForm1のtextBoxに値を入れようと思って

((TextBox)fm.Controls["textBox" + No.ToString()]).Text = "hoge";

としましたがなぜか入力されません。
Form2が開いているときにForm1のtextBoxに値を入力するにはどのようにしたらよいのでしょうか?
textBoxのModifiersプロパティをPublicにしてみましたが、ウンともスンとも反応がないのです。

そもそも私の考え方が間違っていると思うのですが、どのように対応したらよいのでしょうか?
よろしくお願い致します。

お礼日時:2010/10/25 16:35

string result = ((TextBox)fm.Controls["textBox" + No]).Text;


で、どうでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます。これでうまくいきました。

お礼日時:2010/10/25 16:35

フォームのControlsコレクションから取得すればいいのではないかと思います



// int nn にテキストボックスの何番目かを覚えておく
Control[] ctls = Controls.Find( "textBox" + nn.toString(), false );
if ( ctls.Length > 0 )
{
  TextBox txt = (TextBox)ctls[0];
  // ここにやりたい処理を記述
  // txt.Text = "hoge"; など
}

といった具合で ・・・

この回答への補足

少し修正して

Form1 fm = new Form1();
int nn = 1; //例として1とする
Control[] ctls = fm.Controls.Find( "textBox" + nn.toString(), false );
if ( ctls.Length > 0 ){
 TextBox txt = (TextBox)ctls[0];
 txt.Text = "hoge";
 MessageBox.Show("入力されました");
}

としましたらif文の中身はMessageBoxが表示されたので実行されたのですが、textBox1には"hoge"が入力されませんでした。
No3さんへのお礼と同じで、Form2が開いている状態ではForm1のコントロールには入力できないようなのです。

補足日時:2010/10/25 16:47
    • good
    • 0
この回答へのお礼

ありがとうございます。そのような方法もあるのですね。
試してみたいと思います。

お礼日時:2010/10/25 16:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報

このQ&Aを見た人がよく見るQ&A