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

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

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

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

Q&A

解決済

2回答

2918閲覧

【C#】メインのフォームを閉じるときに、サブフォームで保存ボタンを押していないときに警告を出したい。

Satochan24

総合スコア113

C#

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

0グッド

0クリップ

投稿2015/09/03 03:01

C#で、プロジェクト1つ1つを登録するシステムの改修をしています。
作業漏れを防ぐため、タイトルのような、サブフォームで保存ボタンを押していないときに、メインフォームの右上の閉じるボタンを押したときに、
警告メッセージを出したいと思っています。

サブフォームのクラスの保存ボタンのイベントハンドラにフラグを設置し、それが1となっているか確認し、なってなければ閉じる処理で
警告をだせばいいだろうと考え、コードを書いてみたのですが…

今、困っているところが、変数の受け渡しがうまくいかないことです。
ソースを一部書きます。

メインフォームで、BaseStationRegisterContentViewクラスをインスタンス化して、そのFlgを見に行けばいいかなと思ったんですが、
「uintは無効です。」とパラメータに問題ありです。引数の_Id、house_id
はサブフォームのBaseStationRegisterContentViewクラスだけが持っています。
どう修正すればよいでしょうか?

//MainForm.cs using SmartFoundation.Views.ContentsView; //他のusingは省略 namespace SmartFoundation { public partial class MainForm : Form { BaseStationRegisterContentView bsrc; public MainForm() { InitializeComponent(); ConfigInstance.Load(); //uint golfhouseid = BaseStationRegisterContentView.golfhouseid; this.Text = Resources.TITLE; var signinAction = new Action<LoginInfo>((loginInfo) => { DBController.SetConnection(loginInfo.Server, loginInfo.DBName, loginInfo.Account, loginInfo.Password); if (DBController.TestConnection()) { ConfigInstance.Config.Server = loginInfo.Server; ConfigInstance.Config.DBName = loginInfo.DBName; ConfigInstance.Config.Account = loginInfo.Account; ConfigInstance.Save(); this.Controls.Remove(_body); _body = new MainView(); this.Controls.Add(_body); } else { MessageBox.Show(Resources.ERROR_CONNECTION, Resources.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error); } }); _body = new LoginView(signinAction); this.Controls.Add(_body); } private UserControl _body; // フォームのFormClosingイベントハンドラ private void MainForm_FormClosing_1(object sender, FormClosingEventArgs e) { bsrc = new BaseStationRegisterContentView(uint id); if (bsrc.Flg == 0) { //閉じるときの処理 DialogResult ret; ret = MessageBox.Show("[設定]タブで、【保存】ボタンを押していない可能性があります。\r\n本当に終了しますか?" , "警告", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); if (ret == DialogResult.Cancel) e.Cancel = true; } } } }
// BaseStationRegisterContentView.cs // usingステートメント省略 namespace SmartFoundation.Views.ContentsView { public partial class BaseStationRegisterContentView : UserControl { BaseStation baseStation; uint _Id; // 保存ボタン押下確認フラグ private int SaveBaseSettingFlg; public int Flg { get { return SaveBaseSettingFlg; } } public uint id { get { return _Id; } } public BaseStationRegisterContentView(uint house_id) { InitializeComponent(); this.Dock = DockStyle.Fill; _Id = house_id; // 保存ボタン押下確認フラグを初期化 SaveBaseSettingFlg = 0; try { GetBaseStation(); } catch (Exception ex) { MessageBox.Show(Resources.EXCEPTION_ERROR_TITLE + "\n" + ex.Message + "\n\n" + Resources.EXCEPTION_ERROR_STACK_TRACE + "\n" + ex.StackTrace); } } public void GetBaseStation() { var list = DBController.BaseStationManager.Select(_Id); baseStation = list.FirstOrDefault(); if (baseStation != null) { //省略 } } bool isDouble(string text) { double value = 0; if (double.TryParse(text, out value)) { return true; } return false; } private void buttonUpdate_Click(object sender, EventArgs e) { if ( //省略) { MessageBox.Show(Resources.ERROR_DATA_EMPTY, Resources.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (//省略) { MessageBox.Show(Resources.ERROR_DATA_OUTSIDE_NUMERIC, Resources.TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { var updateDate = DateTime.Now; var data = new BaseStation() { id = _Id, //省略 create_user_id = 0, create_date = updateDate, update_user_id = 0, update_date = updateDate, delete_flg = false, }; if (baseStation == null) { DBController.BaseStationManager.Insert(data); } else { DBController.BaseStationManager.Update(data); } GetBaseStation(); // 保存ボタン押下確認フラグを1に設定 SaveBaseSettingFlg = 1; // 保存完了メッセージ MessageBox.Show("保存しました。" , "保存完了", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show(Resources.EXCEPTION_ERROR_TITLE + "\n" + ex.Message + "\n\n" + Resources.EXCEPTION_ERROR_STACK_TRACE + "\n" + ex.StackTrace); } } private void numericKeyPress(object sender, KeyPressEventArgs e) { if ('0' <= e.KeyChar && e.KeyChar <= '9') { } else if (e.KeyChar == 22) { } else if (e.KeyChar == '\b') { } else if (e.KeyChar == '.') { if ((sender as TextBox).Text.Contains('.')) { e.Handled = true; } } else { e.Handled = true; } } } }

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

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

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

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

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

Tak1wa

2015/09/03 03:11

こんにちは。 BaseStationRegisterContentView がよくわからないのですが、 そもそもサブフォームというものはUserControlですか? であればMainFormCloseで呼び出しているコンストラクタは生成処理ですよね。 それともMainFormのコンストラクタでMainView、LoginViewというのを生成していますがこれがサブフォームでしょうか? メインフォームとサブフォームの関連がイマイチ掴めませんのでその辺りを明確にして頂けると。
Satochan24

2015/09/03 04:20

説明不足ですみません。メインフォームの中にサブフォームが複数、タブとして存在しています。その中の一つのタブに入力欄と保存ボタンがある状態です。MainViewというのは、MainFormの右ペインの背景部分のようなViewですね。左ペインにプロジェクトの階層が表示されます。こんな説明でよろしかったでしょうか?
Satochan24

2015/09/03 09:31

すみません。追記ですが、ビルドしたメインフォームには、サブフォームがタブとして埋め込まれていますが、ビルド前の画面は、それぞれ独立している状態です。 コードを見ると、メインフォームにサブフォームをAddメソッドで追加しているだけのようですが…
guest

回答2

0

ベストアンサー

こんにちは。

エラーが起こっている直接の原因については、パラメータに問題ありの通りで
かっこの中にuint idと書かれているためと思います。(uintが不要)

C#

1bsrc = new BaseStationRegisterContentView(uint id);

例えば、以下のような形で記述が必要と思います。

C#

1uint id = 1; /* 仮に1としてますが、idに設定する適切な値 */ 2bsrc = new BaseStationRegisterContentView(id); // 渡す値のみを書く

BaseStationRegisterContentViewがサブフォームに該当すると思いますが、
このコードだとMainFormのClosingのタイミングでサブフォームを表示(作成)する流れにならないでしょうか。
bsrcを使うなら、作成したタイミングで保持しておく事が必要と思います。

便宜上 Closingの中に書いているなら無視してください。

後は気にしておいた方が良いと思えた点として、以下の2点が思い浮かびました。

(1)Closing(保存判定)のタイミングで、BaseStationRegisterContentViewが存在しているか?
→生成していない。生成したが、Closing前に破棄される可能性

(2)BaseStationRegisterContentViewが複数(2つ以上)存在しえないか?

投稿2015/09/03 04:06

sgr-2

総合スコア294

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

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

Satochan24

2015/09/03 04:52

回答有難うございます。(1)は存在していますね。メインフォームの中に複数タブがあり、その一つのタブがBaseStationRegisterContentViewです。(2)は1つだけのはずです。僕がクローズメソッドの中で誤って作成してしまったものを含めると2つになりますが… 他の方からも指摘されましたが、最初の初期化時に作成されたはずのインスタンスを持ってこないと意味がないということで、そのインスタンス名がDesignersファイルを見ても分からない状況です。
sgr-2

2015/09/03 05:07

BaseStationRegisterContentView(以下サブフォーム)は、メインフォーム上に存在するタブの要素の1つとの事ですが、このサブフォームはVisual Studioのデザイナを使ってメインフォーム上に配置しているか?/コード上で生成しているか?で違ってくると思っています。 (a)Visual Studioのデザイナで配置  デザイナ上で配置した場合は、(メインフォーム上で)該当サブフォームを選択した状態でプロパティウインドウを見ると、Nameの項目に名前が指定されていると思います。この名前で参照できないでしょうか?  Name項目が「SubForm1」なら「SubForm1.Flg」 (b)コード上で作成  この方法であれば、「new BaseStationRegisterContentView(...)」で作っていると思うので、この戻り値になると思います。  Closingの中で書いていたのと同じなら、「brsc.Flg」
Satochan24

2015/09/03 05:19

回答有難うございます。ビルドすると、メインフォーム上にサブフォームが現れるのですが、Visual Studio上では、別々のフォームになっています。 僕も最初、不思議な作りだと思いました。 特に、今のところ、newしている個所が見つからず、brsc.Flgしても、別物のインスタンスなので、常に0になってしまいます。
Satochan24

2015/09/03 05:36

newしているところ、ありました。 別のクラスの中でした。 しかし、これは無名でインスタンス化してるから、簡単には持ってこれないかと… どうやって、このインスタンスを取得するかが問題ですね。 namespace SmartFoundation.Views { public partial class CourseContentsView : UserControl { IList<TabPage> courseTab = new List<TabPage>(); IList<Course> courseList; House _House; TabPage tabPage_CRegister = new TabPage("C設定"); TabPage tabPage_GRegister = new TabPage("G設定"); TabPage tabPage_BaseStation = new TabPage("基地設定"); TabPage tabPage_HouseUser = new TabPage("ユーザ設定"); public CourseContentsView(House house) { InitializeComponent(); this.Dock = DockStyle.Fill; _House = house; tabControl.TabPages.Add(tabPage_CRegister); //tabControl.TabPages.Add(tabPage_GRegister); tabControl.TabPages.Add(tabPage_BaseStation); tabControl.TabPages.Add(tabPage_HouseUser); tabPage_CRegister.Controls.Add(new CRegisterContentView(_House.house_id)); tabPage_GRegister.Controls.Add(new GRegisterContentView(_House.house_id)); tabPage_BaseStation.Controls.Add(new BaseStationRegisterContentView(_House.house_id)); (以下、省略)
sgr-2

2015/09/03 07:16 編集

ありがとうございます。 なるほど階層の深いところで作成されているのですね。 この状態でストレートに該当のBaseStationRegisterContentViewを探って・・・というのは易しくなさそうです。 CourseContentsView以下には、他にも作成(CRegisterContentViewなど)を行っているので 「BaseStationRegisterContentViewを探す→Flgを確認」の方法は回避して、異なるアプローチを取った方が良いかも知れません。 アプリケーションの規模であったり、他のコントロールとの絡みなど全体が見えないので、簡単には言えないのですが、 対象プロジェクトの中で共通してアクセスできるclassを1つ作って(共有変数のような)、その値を参照する。というアプローチの方が単純化できそうです。 例えば、シンプルに書いてしまいますが class 共有変数 { public static bool IsSaved = false; // 終了前に保存が必要か否かの判定に利用 .... } # 状況によっては、良い対策と言えない可能性がありますので考慮が必要になりそうです。 # 既に似たような事例に対して解決する方法が実装されているかも知れませんし、 # メンバーの方、該当あたりを実装した方に聞く、相談するのが可能であれば # それが一番安全と思います。
Satochan24

2015/09/03 09:35

回答有難うございました。設計した人が今週は出張中なので、来週聞いてみようかと思います。 それにしても、単にクラス間の変数の受け渡しだけなのに、階層が深いだけで簡単にできなかったりするんですね。初心者の私も驚きです。 明日、別のアプローチ(共通にアクセスできるクラスなど)を検討してみます。 有難うございました。
Satochan24

2015/09/04 02:15 編集

実現できました!別アプローチで、 共通にアクセスできる別クラスで変数をstaticで作成し、 保存ボタン押されたら変数をtrueにするというやり方で、いとも簡単に実現できました! どうも有難うございました。
guest

0

BaseStationRegisterContentViewの配置をGUIツールから行っていると思いますが、
InitializeComponent()の中でインスタンスを作成しているので、MainForm_FormClosing_1メソッドの中で newしても意味がありません。

GUIツールで指定したフィールド名をbsrcの代わりに利用すればうまくいきませんか?

投稿2015/09/03 03:50

hello-world

総合スコア1342

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

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

Satochan24

2015/09/03 04:45

GUIツールで指定したフィールド名? フォーム画像のプロパティ欄をみると、デザインのNameで、そのままBaseStationRegisterContentViewとなっていますが、ここではないでしょうか?ちなみにこの名前をbsrcの代わりに使ってみましたが、エラーになります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問