DOBON.NET DOBON.NETプログラミング掲示板過去ログ

クラスファイルからフォームにあるクラスの関数が実行できません。

環境/言語:[C#]
分類:[.NET]

Visual Studio Express 2013のC#でフォームアプリケーションを作成しています。

フォームがデザインされているForm1.cvというファイルの中のFormクラスの中に

public void showInput(int i)
{
if (i == 0)
{
textBox1.Visible = true;
button1.Visible = true;
} else {
textBox1.Text = "";
textBox1.Visible = false;
button1.Visible = false;
}
}
というような関数があります。
これを別に作ったクラスファイルEvent.cv内のEventクラス内の関数で
     Form1 frm = new Form1();
frm.showInput(0);
というように記述し、呼び出そうとしたのですが、エラーなくデバックでき、textBox1もbutton1も表示されない状況です。

別のコードでVisibleプロパティがfalseになっている可能性があるかと思って調べてみましたが、違いました。直前に記述した命令はきちんと実行されています。

今までVBを使っていてC#でプログラミングするのは初めてで、色々異なるところがあって戸惑ってます。どこがおかしかったのか教えていただけると助かります。
2014/05/01(Thu) 20:52:40 編集(投稿者)

■No32330に返信(はーむさんの記事)
> これを別に作ったクラスファイルEvent.cv内のEventクラス内の関数で
>      Form1 frm = new Form1();
>           frm.showInput(0);
> というように記述し、呼び出そうとしたのですが、
> エラーなくデバックでき、textBox1もbutton1も表示されない状況です。

その2行を日本語で説明すると
 「新しい Form1 を作って、そのフォームに対して showInput を呼び出す」
となります。

つまり、2個目の Form1 ができているわけです。
そして、その2個目の Form1 は表示されていないので、あなたが見ている1個目の Form1 では
何も起きなかったという状態になっています。


さて、解決するためには、「すでに作られている(表示されている)Form1」の参照を手に入れる
必要があります。
そのクラスは Form1 の参照を受け取ることはできないのでしょうか。
クラスの呼び出し方についてコード片でも結構ですので示せませんか?


<実現例>
〜 Form1 側〜
// UtilityClass のコンストラクタに自分の参照(this = Form1)を渡す
UtilityClass utility = new UtilityClass(this);
utility.TestMethod();

〜 UtilityClass.cs 〜
public class UtilityClass
{
  private readonly Form1 _form;

  public UtilityClass(Form1 form)
  {
    // コンストラクタ引数でForm1の参照をもらってメンバー変数で覚える
    _form = form;
  }

  public void TestMethod()
  {
    // メンバー変数に覚えておいたForm1の参照に対して操作する
    _form.showInput(0);
  }
}

※相互参照と呼ばれる状態になるのであまりよくない設計ではありますが、
まずは初歩として理解しやすい形として提示しています。
なお、何が起きているかをもう少し視覚的に捉えるなら、今のコードを以下のように書き換えると理解しやすいでしょう。


Form1 frm = new Form1();
frm.showInput(0);
frm.Show();
とても親切に教えていただきありがとうございます。
今まで全く仕組みが分からなかったのでとても勉強になりました。

クラスの呼び出しは関数の外で行うようにしていました

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

Event Event = new Event();
private void pictureBox1_Click(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
changePos();
Event.click(x, y);
Event.draw(g, modeShow);

if (Event.mode != 0)
{
timerMode.Enabled = true;
}

if (Event.mode == 2)
{
textBox1.Visible = true;
button1.Visible = true;
} else if (Event.mode == 1) {
textBox1.Visible = false;
button1.Visible = false;
}
}
}

教えていただいた実現例をもとにEvent Event = new Event(this);というように記述を改めたのですが、「キーワード 'this' は現在のコンテキストでは使用できません。」というエラーが出てしまいました。

関数の中で宣言するとうまく呼び出せなくなってしまいました。
2014/05/01(Thu) 23:37:49 編集(投稿者)

■No32333に返信(はーむさんの記事)
> 教えていただいた実現例をもとにEvent Event = new Event(this);というように記述を改めたのですが、
> 「キーワード 'this' は現在のコンテキストでは使用できません。」というエラーが出てしまいました。
> 関数の中で宣言するとうまく呼び出せなくなってしまいました。

メソッドの外、つまりフィールド変数の右側に書く形で初期化する場合、エラーの通り、this は使えません。
コンストラクタで書いてください。

public Form1()
{
  InitializeComponent();
  _event = new Event(this);
}

Event _event;


あと、クラス名と大文字小文字も含めて同じフィールド変数名は混乱を招くのでやめた方がよいですよ。
今書いている Event がクラスなのか、フィールド変数なのか、自分でもわからなくなりますし、場合によってはコンパイルエラーになります。


※ソースコードを書く場合は図表モードが便利です。空白によるインデントが消えません。
変数の宣言と初期化を別々に行うのですね、思いつきませんでした。
とても貴重な経験になりましたありがとうございます。

フィールド変数名も図表モードについても、これから気を付けようと思います。
細かいところまで気を遣っていただき、本当に助かりました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板