C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

親フォームからの継承

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■93458 / inTopicNo.1)  親フォームからの継承
  
□投稿者/ じょこびっち (40回)-(2019/12/12(Thu) 14:43:58)

分類:[C#] 

親フォームから測定機器と接続して子フォームから設定値を機器へ送りたいです。
しかし、子フォームで親の状態を引き継いでいない(インスタンス、機器との接続状況)ため
改めて子側でインスタンスを生成して接続しなければいけません。(下記1、2の動作)
子は親の延長でボタンなどを別のフォームに置いただけで、単純に設定値を送ればいいと考えていました。

子フォームで親の状態を引き継いだまま子フォームを動作させるにはどうすればいいでしょうか?
うまく説明できないのでやりたい事を理解していただき助言してもらえると助かります。よろしくお願いします。

現在
1、親フォームを起動
ResourceManager rm = new ResourceManager();
FormattedIO488 inst = new FormattedIO488();
2、測定機器と接続
inst.IO = rm.Open("接続コマンド") as IMessage;
3、子フォーム用ボタンenabled = true
4、子フォーム用ボタンをクリック
private void 子フォームボタン_Click(object sender, EventArgs e)
{
Form2 newForm = new Form2();
newForm.ShowDialog(this);
}

子フォーム
private void 設定ボタン_Click(object sender, EventArgs e)
{
if(ComboBox1.SelectedIndex == 0)
{
inst.WriteString("コマンド");&#8656;inst使えない
}
}
引用返信 編集キー/
■93459 / inTopicNo.2)  Re[1]: 親フォームからの継承
□投稿者/ 魔界の仮面弁士 (2525回)-(2019/12/12(Thu) 14:56:55)
No93458 (じょこびっち さん) に返信
> ResourceManager rm = new ResourceManager();
> FormattedIO488 inst = new FormattedIO488();

アプリ全体で一つのインスタンスがあれば良いなら、Program.cs 内で
 public static ResourceManager rm = new ResourceManager();
のようにしておいて、各フォームから Program.rm.Open("接続コマンド") のように呼び出すとか。


アプリ全体で複数インスタンスが必要ではあるけれど、
親フォームと子フォームで同じインスタンスとしたいなら、
子フォーム側にプロパティあるいは引数付コンストラクタを追加して、
それを通じて受け渡すようにするとか。


 ResourceManager rm = new ResourceManager();
 using (Form2 newForm = new Form2(rm)) // ★
 {
   newForm.ShowDialog(this);
 }


> 子は親の延長でボタンなどを別のフォームに置いただけで、単純に設定値を送ればいいと考えていました。
別案としては、子フォームにイベントを自作し、
子フォーム側のボタン押下等を親フォーム側で受けるようにするとか。
(FontDialog クラスの Apply イベントを扱う時のように)



> newForm.ShowDialog(this);
ShowDialog で開いたフォームを閉じた場合、それは単に非表示になるだけなので御注意ください。

Show メソッドで開いた場合は、フォーム終了時に破棄されるのですが、
ShowDialog メソッドで呼ぶ場合は、子画面終了後に Dispose の呼び出しが必要です。
(using ブロックの利用を推奨)





引用返信 編集キー/
■93460 / inTopicNo.3)  Re[1]: 親フォームからの継承
□投稿者/ 774RR (762回)-(2019/12/12(Thu) 15:04:07)
通信資源は (SerialPort や TCP PORT x 番) 等は2重に開くことができないので、
親フォームが通信資源を開いているとき、子フォームが改めて開くという設計はしないっす。

親フォームで開いた通信資源をそのまま子フォームに渡して共有するのが普通かな?

FormChild.cs でも inst を保持できる(メンバに含ませる)ようにして
FormMain.cs では
案1
using (FormChild f = new FormChild(this.inst)) // コンストラクタで指定するとか
{
    f.ShowDialog();
}
案2
using(FormChild f = new FormChild())
{
    f.Inst = this.inst; // FormChild にプロパティを設けて後から渡すとか
    f.ShowDialog();
}

親フォーム側で UI スレッドと通信スレッドを別にして UI 側が通信で阻害されないようにしているとき
子フォームが行いたい通信は、親フォームから見て「途中に介入」したことになるわけで、
通信が混乱しないよう「直列化」シリアライズ処理が必要になるかもしんまいです。

引用返信 編集キー/
■93463 / inTopicNo.4)  Re[2]: 親フォームからの継承
□投稿者/ じょこびっち (41回)-(2019/12/12(Thu) 16:54:14)
>  ResourceManager rm = new ResourceManager();
>  using (Form2 newForm = new Form2(rm)) // ★
>  {
>    newForm.ShowDialog(this);
>  }

お二人からのアドバイスに従ってusingでやろうとしたのですが
「Form2には引数1を指定するコンストラクターは含まれていません」とエラーになります。
引数を入れてエラーにならないようにするにはどうすればいいのでしょうか?


>>newForm.ShowDialog(this);
> ShowDialog で開いたフォームを閉じた場合、それは単に非表示になるだけなので御注意ください。
>
> Show メソッドで開いた場合は、フォーム終了時に破棄されるのですが、
> ShowDialog メソッドで呼ぶ場合は、子画面終了後に Dispose の呼び出しが必要です。
> (using ブロックの利用を推奨)

そうなんですか?ご指摘ありがとうございます。
買ったばかりの本には書いてありませんでした。失敗しました。
弁さんに買う本のアドバイスを貰うべきでした。
Disposeの後にnullでプロパティ値を空にしたほうがいいのでしょうか?

774RRさん
> 親フォーム側で UI スレッドと通信スレッドを別にして UI 側が通信で阻害されないようにしているとき
> 子フォームが行いたい通信は、親フォームから見て「途中に介入」したことになるわけで、
> 通信が混乱しないよう「直列化」シリアライズ処理が必要になるかもしんまいです。
やはりそうですよね。なんとなくそうだろうとは思っていたのですが自分にはそれを実現するだけの実力はないもので・・・。
「直列化」シリアライズ処理!
覚えておきます。
引用返信 編集キー/
■93464 / inTopicNo.5)  Re[3]: 親フォームからの継承
□投稿者/ 774RR (763回)-(2019/12/12(Thu) 19:26:46)
> 引数を入れてエラーにならないようにするにはどうすればいいのでしょうか?
そういうコンストラクタを FormChild 側に作ってください。
既存のコンストラクタ(引数なし)とは別のコンストラクタ(引数アリ)を作ってもいいし
既存のコンストラクタを書き換えて引数を追加してもいいです。

public partial class FormChild : Form
{
    FormattedIO488 inst;
    public FormChild(FormattedIO488 inst0)
    {
        inst = inst0;
        InitializeComponent();
    }
}

シリアライズっつても
- 単に排他するだけでもいいし
- 通信コマンドをキューに入れてもいいし
- もっと本格的になんかしないといけないかもしれないし
- もしかしたら何もしなくてもいいかもしれない
その辺は全体的な作り方次第で違うのでコード断片だけ見ても第三者には判断つかないっす。

計測器側にしてみれば PC ソフト側にメインとサブがあるとかはどうでもよいわけで、
コマンド A を処理して返事 A を返すだけのことです。
コマンド B を処理して返事 B を返すだけのことです。
コマンド A に対して返事 A を返す前にコマンド B が送られたらどう挙動するかは計測器次第。
機器側の動きおよび PC ソフト側の動きがその辺で混乱を招かないのであれば何もしなくていいっす。
(あなたの PC ソフト側で混乱するのであれば、何らかの対処は必要)

--

Dispose() したらそのあとは当該オブジェクトを触っちゃだめです。

関数内自動変数 something であるとして
DisposableObject something = new DisposableObject();
...
Dispose(something); // これ以後は something に対して呼び出しを行ってはダメ
something = null; // は不要でしょう(意味がない)

引用返信 編集キー/
■93470 / inTopicNo.6)  Re[4]: 親フォームからの継承
□投稿者/ じょこびっち (42回)-(2019/12/13(Fri) 11:02:01)
No93464 (774RR さん) に返信
> > 引数を入れてエラーにならないようにするにはどうすればいいのでしょうか?
> そういうコンストラクタを FormChild 側に作ってください。
> 既存のコンストラクタ(引数なし)とは別のコンストラクタ(引数アリ)を作ってもいいし
> 既存のコンストラクタを書き換えて引数を追加してもいいです。
>
> FormattedIO488 inst;

出来ました。
しかし、「フィールドを読み取り専用にします」のメッセージが出ます。
気にしなくてもいいのでしょうか?
引用返信 編集キー/
■93474 / inTopicNo.7)  Re[5]: 親フォームからの継承
□投稿者/ 魔界の仮面弁士 (2527回)-(2019/12/13(Fri) 11:19:08)
No93470 (じょこびっち さん) に返信
>>FormattedIO488 inst;
> しかし、「フィールドを読み取り専用にします」のメッセージが出ます。
> 気にしなくてもいいのでしょうか?

変数inst を、そのコンストラクタ「以外」の場所から、
 this.inst = 何某;
などと書き換える必要があるか無いか、ということです。

コンストラクタでしかセットしないのであれば、フィールド変数宣言を
 readonly FormattedIO488 inst;
にして、書き換えを防いでください。

この場合、読み取り専用になるのは inst 自身だけです。
inst のメンバーまでも読み取りになるわけではないので、
 inst.IO = rm.Open("接続コマンド") as IMessage;
などは引き続き行えます。
引用返信 編集キー/
■93475 / inTopicNo.8)  Re[5]: 親フォームからの継承
□投稿者/ 774RR (765回)-(2019/12/13(Fri) 11:25:19)
> しかし、「フィールドを読み取り専用にします」のメッセージが出ます。
日本語訳が微妙で「フィールドを読み取り専用にすることを推奨します」のほうが適切かな。

> 気にしなくてもいいのでしょうか?
要するにコンストラクタ内で一度初期化したっきり二度と変更しないフィールドであるなら
readonly FormattedIO488 inst;
にしたほうがバグを招かなくていいと思うんだけど、どう? と解析ツールが主張している。

この inst を (FormChild 内で) 変更する予定があるなら現状のままでないとまずいし
(同じ計測器を2台つないで切り替えて使うような場合にはこれが大いにありそう)

1台しかつながないので切り替えることは絶対ないなら readonly を付加するほうがよさそうだし

その辺を決めるのが設計っす。

プログラマが、正しくコード解析ツールの主張を理解し修正箇所を取捨選択するならよし、
プログラマが、コード解析ツールの結果に右往左往するのはばかげている。

引用返信 編集キー/
■93476 / inTopicNo.9)  Re[6]: 親フォームからの継承
□投稿者/ じょこびっち (43回)-(2019/12/13(Fri) 11:48:40)
No93474 (魔界の仮面弁士 さん) に返信

> 変数inst を、そのコンストラクタ「以外」の場所から、
>  this.inst = 何某;
> などと書き換える必要があるか無いか、ということです。
>
> コンストラクタでしかセットしないのであれば、フィールド変数宣言を
>  readonly FormattedIO488 inst;
> にして、書き換えを防いでください。

書き換える予定はないのでReadonlyにしました。
弁さん、774RRさんありがとうございました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ