■77141 / ) |
Re[9]: 親フォームから子フォームのメソッドへアクセス |
□投稿者/ ゆーきゃん (54回)-(2015/09/16(Wed) 16:53:33)
|
■No77136 (774RR さん) に返信
> 2015/09/16(Wed) 12:45:22 編集(投稿者)
>
> そもそも論として
> 「親フォームが子フォームの中に手を突っ込む(=想定しないタイミングでメンバを呼ぶとか)」
> 「子フォームが親フォームの中に手を突っ込む」
> ってのは設計上の責任分担ができていない証拠であって、「オブジェクト指向の本来の姿ぢゃない」わけだ。
> そういう「お互いに強依存する」フォームって流用ができないぢゃないか。
>
> オブジェクト指向的に間違った設計をしてしまっているから、実装が簡単でないんだよ。
> (間違ったコードを容易に実装できないように言語仕様が作られている)
>
> 既に指摘があるように Form2.ShowDialog() するってことはモーダルな動作をさせようとしている
> モーダルってのはよくある [OK] [キャンセル] 形式の操作をするものだ
> 設定変更モーダルダイアログを
> - キャンセル終了したら、ダイアログ上での操作は全て捨てられて元データは一切変化しないべきだし
> - OK終了したら元データが変化すべき
> なのであって Form.ShowDialog() ってそういう使い方をするように作られている。
> (この際 [適用] Apply はちょっとおいておく)
>
> この件、オイラなら次のように設計する
> - test1.dat からデータをもらったり書き戻すのは Form1 の仕事であって Form2 にあるべきではない。
> - Form2 は Form1 からもらったデータを表示し、変更を受付け、OK終了したらデータを返せる」ように作る
> - Form1 は Form2 がOK終了したら Form2 からデータをもらって更新する
>
> Form1 の void button1_Click(object sender, EventArgs e)
> {
> using (Form2 fm2 = new Form2())
> {
> fm2.なんとかプロパティ = <form1 の持ってるデータ1>;
> fm2.かんとかプロパティ = <form1 の持ってるデータ2>;
> if (fm2.ShowDialog() == DialogResult.OK)
> {
> <form1 の持ってるデータ1> = fm2.なんとかプロパティ;
> <form1 の持ってるデータ2> = fm2.かんとかプロパティ;
> Invalidate(); // Form1 自分自身の画面更新
> }
> }
> }
>
> Form.ShowDialog で using (Dispose) が必要なのは、
> Form2 の画面がOKで閉じた後に なんとかプロパティ にアクセスできるようにするためだよ。
> 必要なデータを拾い上げ完了するまで Dispose させないための工夫。
>
オブジェクト指向の考え方を含めたお答えありがとうございます。
774RR様のお答えを元に少しプログラムを書き換えてみました。
しかし、自分で見ても無駄の多いプログラムとわかるぐらい正直言ってひどい出来だと思います。
1.test1.dat からデータをもらったり書き戻すのは Form1 の仕事であって Form2 にあるべきではない。
とのことから、yomikomiメソッドをForm1へ移動させました。
データを書き込む際は、form2のボタンを押した際なので、そのまま維持しました。
2.Form2 は Form1 からもらったデータを表示し、変更を受付け、OK終了したらデータを返せる」ように作る
Form1 ←→ Form2 のデータの受け渡し方法が上手くできませんでした。
お手数おかけして申し訳ないのですが、お答えアドバイス願えませんでしょうか。
以下のプログラムですと、Form2からForm1の変数などをもらいに行くとき、Form1を初期化してしまっていると思います。初期化せずに受け取りに行きたいのですが、調べて試行錯誤してみたのですが、思い通りの結果を出すことができませんでした。
●Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
namespace test1
{
public partial class Form1 : Form
{
public float x1;
public float y1;
public float x2;
public float y2;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
yomikomi();
}
public void pictureBox1_Paint(object sender, PaintEventArgs e)
{
draw(sender, e);
}
public void yomikomi()
{
FileStream fs = new FileStream(@"c:\data\test1.dat", FileMode.Open, FileAccess.Read); // ファイルを開く
BinaryReader br = new BinaryReader(fs); // ファイルの読み取り
x1 = br.ReadSingle(); // 4バイト浮動小数点値を読み取り、4バイト進める
y1 = br.ReadSingle(); // //
x2 = br.ReadSingle(); // //
y2 = br.ReadSingle(); // //
fs.Close(); // ファイルを閉じる
}
public void draw(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Green, x1, y1, x2, y2);
}
private void button1_Click(object sender, EventArgs e)
{
using (Form2 fm2 = new Form2())
{
fm2.ShowDialog();
yomikomi();
pictureBox1.Invalidate();
}
}
}
}
● Form2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
namespace test1
{
public partial class Form2 : Form
{
Form1 fm1 = new Form1(); // form1の変数が初期化されてしまう・・・ form1を初期化せずアクセスする方法を模索中
public Form2()
{
InitializeComponent();
}
private void textBox1_TextChanged_1(object sender, EventArgs e)
{
fm1.x1 = int.Parse(textBox1.Text);
pictureBox2.Refresh();
}
private void textBox2_TextChanged_1(object sender, EventArgs e)
{
fm1.y1 = int.Parse(textBox2.Text);
pictureBox2.Refresh();
}
private void textBox3_TextChanged_1(object sender, EventArgs e)
{
fm1.x2 = int.Parse(textBox3.Text);
pictureBox2.Refresh();
}
private void textBox4_TextChanged_1(object sender, EventArgs e)
{
fm1.y2 = int.Parse(textBox4.Text);
pictureBox2.Refresh();
}
private void button2_Click(object sender, EventArgs e)
{
using (BinaryWriter w = new BinaryWriter(File.OpenWrite(@"c:\data\test1.dat"))) // ファイルの書き込み
{
w.Write(fm1.x1);
w.Write(fm1.y1);
w.Write(fm1.x2);
w.Write(fm1.y2);
}
this.Close();
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
fm1.draw(sender,e);
}
private void Form2_Load(object sender, EventArgs e)
{
fm1.yomikomi();
textBox1.Text = fm1.x1.ToString(); // 読み取った値をtextboxに代入
textBox2.Text = fm1.y1.ToString(); // //
textBox3.Text = fm1.x2.ToString(); // //
textBox4.Text = fm1.y2.ToString(); // //
}
}
}
皆様何度も何度も本当に申し訳ないですが、お答えアドバイスの程よろしくお願い致します。
|
|