質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

4183閲覧

C#で画面を再ロードする方法

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2023/09/20 13:10

編集2023/09/21 12:26

実現したいこと

ここに実現したいことを箇条書きで書いてください。

  • Form2の画面が閉じられたとき、Form1の画面を再度ロードする

前提

C#でイメージ説明
イメージ説明

このようにForm2で入力したデータを元にForm1に結果を表示するシステムを作っています。
Form2のデータはテキストファイルで保存され、Form1のロード時や更新ボタンを押したときに読み込んで使用します。
このシステムは画面を閉じずに常駐して動かしたいので、Form2で新しい入力があったときに保存ボタンで新しくデータを保存して、Form2が閉じられたときにその新しく保存されたファイルを再読み込みしたいのですが、何か良い方法はありませんでしょうか?

該当のソースコード

C#

1//ボタン1をクリックしてForm2を表示する 2private void button1_Click(object sender, EventArgs e) 3 { 4 // Form2のインスタンスを生成 5 Form2 form2 = new Form2(); 6 // form2を表示 7 form2.Show(); 8} 9 10private void Form1_Load(object sender, EventArgs e) 11{ 12//ロード時のファイル読み込み 13if (File.Exists(mastFile)) 14 { 15 //アラームの名前でグループ化してリストを作る 16     //名前をキー,1行全体をvalueとする 17 var alarm = File.ReadLines(mastFile, Encoding.GetEncoding("Shift_JIS")) 18 .Select(x => new { Key = x.Split(',')[0], Value = x, }) 19 .GroupBy(x => x.Key) //名前でグループ化する 20 .Select(x => string.Join(",", x.Select(y => y.Value))) 21 .ToList(); 22 23 string[] alarmList = alarm.ToArray(); //リストを配列化する 24 25 dataGridView1.Rows.Add(alarmList.Length); 26 27 //リストの名前をDataGridViewに入れる 28 for (int i = 0; i < alarmList.Length; i++) 29 { 30 string fileData = alarmList[i]; 31 string[] alarmData = fileData.Split(','); 32 name = alarmData[0].ToString().Replace("\"", ""); 33 dataGridView1.Rows[i].Cells[0].Value = name; 34 35 } 36 37 //マスタファイルを読み込む 38 StreamReader sr = new StreamReader(mastFile, Encoding.GetEncoding("SHIFT_JIS")); 39 int valNum = 0; //数値変換用の変数 40 41 while (!sr.EndOfStream) 42 { 43 //読んだ一行をカンマで区切って配列にする 44 string file = sr.ReadLine(); 45 string[] fileData = file.Split(','); 46      } 47 48 49 50
### 試したこと ### 補足情報(FW/ツールのバージョンなど) .NET Framework4.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hqf00342

2023/09/20 13:45

実現したいことの「Form2の画面が閉じられたとき、Form1の画面を再度ロードする」は (1) 新しいForm1を生成する (2) 既に表示してあるForm1の画面を更新する のどちらでしょうか(今のコードでは(1)) また、「新しく保存されたファイルを再読み込み」し画面に反映する機能(メソッド)はForm1に既に存在しているのでしょうか?
KOZ6.0

2023/09/20 13:54

Form2 を表示するときのコードが重要です。それによって処理が変わりますので提示してください。
fana

2023/09/21 01:40

> Form2が閉じたときにForm1をアクティブにして、Form1がアクティブになったときにファイルの読み込み処理をしよう なんというか,回りくどくないですか? やりたいことが「ファイルの読込処理」なのであれば,単純に/直接的にその「ファイルの読込処理」を実施する手段を用意すれば良いのでは? (「アクティブ」とかいう余計な要素をわざわざ間に挟む理由とは何か?)
fana

2023/09/21 01:42

「アクティブになったとき」という実装だと,「Form2が閉じたとき」以外のタイミングでもその処理が走ることになりかねないと思うのですが,そこは問題ないという考えなのでしょうか?
fana

2023/09/21 01:44

あなたの提示コードでは > Form1 form1 = new Form1(); として,新しいインスタンスを生成していますが,これが所望の処理なのだとすれば, 「Form1のロード時」には件の処理が走る,という話なのですから,特別な対処は何も要らないのではありませんか? (:単にその新しく生成したフォームを表示すればそこで「ロード時」の処理が走るのでは?)
fana

2023/09/21 01:55

おそらく, (1)最初,Form1 が存在し,表示されている (2)あるとき,Form2 を表示する (3) (2)のForm2が閉じられる (4) あなたがやりたいこと(Form1がファイルを読込んで何かする) …という順序で物事が進むのだろうと想像しますが, 上記(2)の時点において,(1)で表示されていた Form1 のインスタンスというのはどうなるのですか? (1)と(4)に登場する Form1 というのは同一のインスタンスなのですか? それとも別人ですか? …といったあたりの話を明確にするべきではないでしょうか? あなたの提示コードだと「(1)と(4)のForm1は別人」という話と見えますが,そうであれば前記したように特別な対処は不要と思えます. そうではなくて「同一人物」たるべきなのであれば,別人をnewで生成するのではなく,元から存在した Form1インスタンスに処理をさせるべきでしょう.
退会済みユーザー

退会済みユーザー

2023/09/21 11:49

おっしゃるように、 (1)最初Form1 が存在し,表示されている (2)Form2画面へのボタンがクリックされたときにForm2 を表示する (3) (2)のForm2が閉じられる (4) Form1がファイルを読込む(読み込んだあと、Form1の画面は更新する) の順序なので、別のインスタンスを生成する必要はなさそうです。勉強不足で申し訳ありません。 ファイルの読み込み処理自体はロード時に実装済みです。Form2の表示とともに該当ソースを質問に追加しました。 Form1は最初に開いた時以外は常に開いている状態なので、そこから再びロードの処理を走らせる方法が質問の趣旨でした。
KOZ6.0

2023/09/21 12:15

コードが崩れています。 編集がうまくいっていないようです。
退会済みユーザー

退会済みユーザー

2023/09/21 12:26

修正しました。
guest

回答4

0

用途にもよりますがForm2は、ShowDialogのほうがいいんじゃないでしょうか。
Form.ShowDialog メソッド (System.Windows.Forms) | Microsoft Learn

ShowDialogは、モーダル(いわゆるダイアログ。閉じないと親を操作できない)でウィンドウを表示します。
Showは、モードレス(ペイントソフトの色選択窓のように常に表示され、どちらも操作可能)でウィンドウを表示します。

Showだとボタンを押すたびにウィンドウが増えていきますし、閉じるのを待つこともできません。
ShowDialogであれば複数開く心配はない(開いている間Form1はいじれないのでそもそもボタンが押せない)し、閉じるのを待つことができます。

もちろんモードレスのまま複数開かないように作ることも可能ですが、いろいろ考慮してそのためのコードを書かなくてはなりません。

cs:Form1.cs

1using System; 2using System.IO; 3using System.Windows.Forms; 4 5 6namespace Qp111xlug8rrwo4 7{ 8 public partial class Form1 : Form 9 { 10 public static string FilePath => @"test.txt"; 11 12 public Form1() 13 { 14 InitializeComponent(); 15 16 // デザイナで変更した各プロパティ(デザイナでやっていればここに書く必要はない) 17 textBox1.Multiline = true; 18 textBox1.ReadOnly = true; 19 20 // ファイルは必ず存在しているとする 21 File.WriteAllText(FilePath, "ようこそ\r\n"); 22 23 LoadFile(); 24 } 25 26 private void LoadFile() 27 { 28 // ファイル読み込み 29 textBox1.Text = File.ReadAllText(FilePath); 30 } 31 32 private void EditButton_Click(object sender, EventArgs e) 33 { 34 var form2 = new Form2(); 35 36 // Form2をモーダルで開き、閉じるのを待つ 37 if (form2.ShowDialog() == DialogResult.OK) 38 { 39 // OKを押して閉じたらならファイル読み直し 40 LoadFile(); 41 } 42 // キャンセルや×で閉じたなら何もしない 43 44 form2.Dispose(); 45 } 46 } 47}

cs:Form2.cs

1using System; 2using System.IO; 3using System.Windows.Forms; 4 5namespace Qp111xlug8rrwo4 6{ 7 public partial class Form2 : Form 8 { 9 public Form2() 10 { 11 InitializeComponent(); 12 13 // デザイナで変更した各プロパティ(デザイナでやっていればここに書く必要はない) 14 okButton.DialogResult = DialogResult.OK; // 押すとShowDialogの戻り値にOKをセットし自動で閉じる 15 cancelButton.DialogResult = DialogResult.Cancel; // 押すとShowDialogの戻り値にCancelをセットし自動で閉じる 16 textBox1.AcceptsReturn = true; 17 textBox1.AcceptsTab = true; 18 textBox1.Multiline = true; 19 20 // ファイル読み込み 21 textBox1.Text = File.ReadAllText(Form1.FilePath); 22 } 23 24 private void OkButton_Click(object sender, EventArgs e) 25 { 26 // OKの時はファイル上書き 27 File.WriteAllText(Form1.FilePath, textBox1.Text); 28 29 // DialogResultを設定してるので勝手に閉じる 30 } 31 32 // Cancelの時は何もする必要はないのでハンドラ自体不要 33 } 34}

アプリ動画

投稿2023/09/21 13:49

編集2023/09/21 20:50
TN8001

総合スコア10040

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2023/09/21 13:52

個人的にはなんでもかんでもモーダルダイアログにするUIは大っ嫌いですが^^;
TN8001

2023/09/24 12:48 編集

> とりあえずForm1のロードとデータの読み込み処理を分ける方法で解決しそうです! > 処理を分けるという発想がなかなかできなかったので、大変勉強になりました。 4件も回答貰って感想これだけかぁ。全然話が通じてないんすね。。。 1年後にもう一度見直してもらうとどういうことを言っていたのかわかるかもしれませんね。
guest

0

ベストアンサー

Form1 の修正サンプルです。

csharp

1private void Form1_Load(object sender, EventArgs e) { 2 // ロード時のファイル読み込み処理は別メソッドとして分離 3 LoadData(); 4} 5 6private void LoadData() { 7 // データ読み込み処理を記述 8} 9 10private void button1_Click(object sender, EventArgs e) { 11 // Form2のインスタンスを生成 12 Form2 form2 = new Form2(); 13 // Form2 が閉じられたイベントをキャッチする 14 form2.FormClosed += Form2_FormClosed; // 追加 15 // form2を表示 16 form2.Show(); 17} 18 19private void Form2_FormClosed(object sender, FormClosedEventArgs e) { 20 // Form2 が閉じられたら読み込み処理を行う 21 LoadData(); 22}
  1. Form_Load の処理中に、データを読み込む処理が書いてあるんですかね?読み込みの処理は分離しましょう。サンプルでは LoadData というメソッドに分離してます。

  2. Form2 のインスタンスを作成したら、FormClosed イベントに Form2_FormClosed メソッドを関連付けます。これにより、Form2 が閉じられたことがわかります。

  3. Form2 が閉じられたら読み込み処理を行います。

注釈なんですが、「Form2 のインスタンスを作成する」なんて必要でしょうか?
それは見ればわかるので、どんな画面を表示するのか書いたほうがいいような気がします。

投稿2023/09/21 12:38

KOZ6.0

総合スコア2721

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/09/24 11:56

コメントが遅くなりました。とりあえずForm1のロードとデータの読み込み処理を分ける方法で解決しそうです! ありがとうございました!処理を分けるという発想がなかなかできなかったので、大変勉強になりました。
guest

0

些細なことかもしれませんが,

Form2が閉じられたとき

という話は,今々の Form2 側の動作から来ているのでしょうけど,
本来的(?)には Form1 側がデータを読込んで表示更新するという処理を実施する必要性があるのは「データが保存(更新)されたとき」だと思う(:「Form2が閉じたとき」ではなくて).

登場人物が2つのフォームしかいない現状では,最も簡単な(直接的な?)形で済ませれば良いでしょうが,
今後あれこれとプログラムが発展していくような話があり得る場合には,個々のフォーム間で直接的にやりとりするのではなく,例えば…

  • 【データを保存(更新)し → データが更新されたことを知る必要があるやつらに「更新されましたぜ」と通知する, という仕事を行うやつ】というのを用意して…
  • Form1 はあらかじめそいつに「じゃあ,そんときには俺に通知してくださいね」と依頼しておき…
  • Form2 はデータの保存処理をそいつにやらせる(→結果としてそいつから Form1 に通知がいく)

…みたいな形を考えてみておいても良いかも…? とか.

投稿2023/09/22 01:51

fana

総合スコア12162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

お二人からモーダルウィンドウとイベントハンドラを使った回答が出ているので、別の方法としてForm2からForm1内の関数を呼び出す例を書きます。
(Form1が先に閉じられる問題はこの例では考慮しません。)

イメージ説明

csharp

1 2// == Form1 ==================== 3public partial class Form1 : Form 4{ 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void フォーム2起動ボタン_Click(object sender, EventArgs e) 11 { 12 var form2 = new Form2(this); 13 form2.Show(); 14 } 15 16 public void UpdateScreen(string message) 17 { 18 //画面を更新。好きに書き換えてください。 19 textBox1.Text = messge; 20 } 21} 22 23// == Form2 ==================== 24public partial class Form2 : Form 25{ 26 private Form1 _form1; 27 28 public Form2(Form1 form1) 29 { 30 InitializeComponent(); 31 _form1 = form1; 32 } 33 34 private void 保存_Click(object sender, EventArgs e) 35 { 36 //Form1の関数を呼び出してデータを反映 37 _form1?.UpdateScreen(textBox1.Text); 38 //必要ならFrom2を閉じる 39 //this.Close(); 40 } 41}

投稿2023/09/21 16:03

編集2023/09/23 03:25
hqf00342

総合スコア394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問