none
フォーム上のコントロールのアクセスについて RRS feed

  • 質問

  • こんにちは。Visual C# 2005 を使って開発している初心者のシュンです。

     

    初歩的な質問なのですが、

     

    今、開発しているプロジェクトには、Form1 とForm2 があります。

     

    Form1のイベントShown でForm2 が表示されます。

     

    Form2 のOKボタンをクリックしたときに、Form1 のToolStrip のEnabled が、false から true に設定したいのですが、なかなかうまくいきません。

     

    もちろん、それらのコントロールのModifier は、Internal に設定をしています。

     

    private void StandardForm_Load(object sender, EventArgs e)
            {
                this.Button1.Enabled = false;
            }

     

    private void Form1_Shown(object sender, EventArgs e)
            {
                Form Form2 = new Form2();

                Form2.StartPosition = FormStartPosition.CenterParent;
                Form2.ShowDialog();
            }

     

    private void OKButton_Click(object sender, EventArgs e)
            {
                Form1 Form1 = new Form1();

                Form1.Button1.Enabled = true;
                this.Close();
             }

    2008年2月7日 4:59

回答

  •  ShunYamaguchi さんからの引用

                Form1 Form1 = new Form1();

     

    new キーワードは文字通り「新しいオブジェクトを作成する」ものです。古いもの、つまり既に存在しているものとは別物になります。既に表示している Form1 とは別物の新しい Form1 が作られたわけです。その新しく作った Form1 のボタンをどうしようが、既に存在している Form1 のボタンには何の影響もありません。

    解決方法は大きく二つ。一つは Form2 がどうやってか「既に存在している Form1 を手に入れる」こと。もう一つが「Form1 自身が自分自身でボタンの設定を変更する」ことです。

     

    一つ目なら、例えば Form2 に Form1 型のプロパティを用意したり、Form1 型の引数を受け取る ShowDialog メソッドを用意すると言ったことが考えられます。

    が、この方法は一般に忌避されます。Form1 はもちろん Form2 を ShowDialog するために Form2 を知っている必要がありますが、それに加え Form2 も Form1 を知ることになり、お互いがお互いに依存してしまって代用が利かなくなるからです。

     

    二つ目は、OpenFileDialog が分かりやすい例になります。OpenFileDialog はファイル名を選択させますが、その選択したファイル名をプロパティとして公開しているだけです。そのプロパティをどうするかはダイアログを開いた人に任されます。決して OpenFileDialog 自身が「自分を開いたフォームのテキストボックスにファイルの内容を書き出す」なんてことはしません。

    つまり、例えば Form2 に IsAcceptted プロパティを用意して、OK ボタンが押されたら IsAcceptted プロパティが true を返すように設定します。Form1 は、ShowDialog の後、このプロパティを確認してボタンを表示するかどうかを決めるわけです。

    これなら、Form2 は Form1 を知る必要がなくなり、例えば Form3 からも Form2 を使って確認ダイアログを出せるようになります。

     

    ところで、ShowDialog メソッドを使用して Form2 を表示されていますね。

    ダイアログとして開かれた Form は多少特殊な点があります。

    まず、一般に ShowDialog で開かれたフォームは、自分を閉じる際、Close メソッドを呼び出しません。DialogResult に値を設定すれば自動的に閉じられます(厳密には非表示になります)。

    ShowDialog を呼び出した側(上記例なら Form1 ですね)は、ShowDialog の返値として上記で設定した DialogResult の値を取得できます。

    また、上述の通り ShowDialog で開いたのを閉じても、実際の動作としては非表示になるだけなので、後片付けとして Form2 の Dispose の呼び出しが推奨されます。

    なお、DialogResult として返値が受け取れるので、単純な確認ダイアログ程度なら IsAcceptted みたいなプロパティを用意するまでもなく、DialogResult を見てボタンの表示非表示を決めることもできます。

    2008年2月7日 6:02

すべての返信

  •  ShunYamaguchi さんからの引用

                Form1 Form1 = new Form1();

     

    new キーワードは文字通り「新しいオブジェクトを作成する」ものです。古いもの、つまり既に存在しているものとは別物になります。既に表示している Form1 とは別物の新しい Form1 が作られたわけです。その新しく作った Form1 のボタンをどうしようが、既に存在している Form1 のボタンには何の影響もありません。

    解決方法は大きく二つ。一つは Form2 がどうやってか「既に存在している Form1 を手に入れる」こと。もう一つが「Form1 自身が自分自身でボタンの設定を変更する」ことです。

     

    一つ目なら、例えば Form2 に Form1 型のプロパティを用意したり、Form1 型の引数を受け取る ShowDialog メソッドを用意すると言ったことが考えられます。

    が、この方法は一般に忌避されます。Form1 はもちろん Form2 を ShowDialog するために Form2 を知っている必要がありますが、それに加え Form2 も Form1 を知ることになり、お互いがお互いに依存してしまって代用が利かなくなるからです。

     

    二つ目は、OpenFileDialog が分かりやすい例になります。OpenFileDialog はファイル名を選択させますが、その選択したファイル名をプロパティとして公開しているだけです。そのプロパティをどうするかはダイアログを開いた人に任されます。決して OpenFileDialog 自身が「自分を開いたフォームのテキストボックスにファイルの内容を書き出す」なんてことはしません。

    つまり、例えば Form2 に IsAcceptted プロパティを用意して、OK ボタンが押されたら IsAcceptted プロパティが true を返すように設定します。Form1 は、ShowDialog の後、このプロパティを確認してボタンを表示するかどうかを決めるわけです。

    これなら、Form2 は Form1 を知る必要がなくなり、例えば Form3 からも Form2 を使って確認ダイアログを出せるようになります。

     

    ところで、ShowDialog メソッドを使用して Form2 を表示されていますね。

    ダイアログとして開かれた Form は多少特殊な点があります。

    まず、一般に ShowDialog で開かれたフォームは、自分を閉じる際、Close メソッドを呼び出しません。DialogResult に値を設定すれば自動的に閉じられます(厳密には非表示になります)。

    ShowDialog を呼び出した側(上記例なら Form1 ですね)は、ShowDialog の返値として上記で設定した DialogResult の値を取得できます。

    また、上述の通り ShowDialog で開いたのを閉じても、実際の動作としては非表示になるだけなので、後片付けとして Form2 の Dispose の呼び出しが推奨されます。

    なお、DialogResult として返値が受け取れるので、単純な確認ダイアログ程度なら IsAcceptted みたいなプロパティを用意するまでもなく、DialogResult を見てボタンの表示非表示を決めることもできます。

    2008年2月7日 6:02
  • こんにちは。中川俊輔 です。

     

    Hongliang さん、大変丁寧で参考になる回答ありがとうございます。

     

    ShunYamaguchiさん、フォーラムのご利用ありがとうございます。

    その後いかがでしょうか?

    問題解決に有用な回答のようでしたので、

    勝手ながらHongliang さんの回答へ回答済みチェックをつけさせていただきました。

     

    問題解決につながる回答があった場合は、なるべく回答済みボタンを押してチェックを付けてください。

    ShunYamaguchiさんはチェックを解除することもできますので、ご確認ください。

     

    それでは!

     

    2008年2月14日 8:23