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

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

ただいまの
回答率

90.62%

  • C#

    6834questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,136

Satochan24

score 78

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;
            }
        }
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Tak1wa

    2015/09/03 12:11

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

    キャンセル

  • Satochan24

    2015/09/03 13:20

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

    キャンセル

  • Satochan24

    2015/09/03 18:31

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

    キャンセル

回答 2

checkベストアンサー

+1

こんにちは。

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

例えば、以下のような形で記述が必要と思います。
uint id = 1; /* 仮に1としてますが、idに設定する適切な値 */
bsrc = new BaseStationRegisterContentView(id); // 渡す値のみを書く

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


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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/03 13:52

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

    キャンセル

  • 2015/09/03 14:07

    BaseStationRegisterContentView(以下サブフォーム)は、メインフォーム上に存在するタブの要素の1つとの事ですが、このサブフォームはVisual Studioのデザイナを使ってメインフォーム上に配置しているか?/コード上で生成しているか?で違ってくると思っています。

    (a)Visual Studioのデザイナで配置
     デザイナ上で配置した場合は、(メインフォーム上で)該当サブフォームを選択した状態でプロパティウインドウを見ると、Nameの項目に名前が指定されていると思います。この名前で参照できないでしょうか?
     Name項目が「SubForm1」なら「SubForm1.Flg」

    (b)コード上で作成
     この方法であれば、「new BaseStationRegisterContentView(...)」で作っていると思うので、この戻り値になると思います。
     Closingの中で書いていたのと同じなら、「brsc.Flg」

    キャンセル

  • 2015/09/03 14:19

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

    キャンセル

  • 2015/09/03 14: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));
    (以下、省略)

    キャンセル

  • 2015/09/03 15:04 編集

    ありがとうございます。
    なるほど階層の深いところで作成されているのですね。
    この状態でストレートに該当のBaseStationRegisterContentViewを探って・・・というのは易しくなさそうです。
    CourseContentsView以下には、他にも作成(CRegisterContentViewなど)を行っているので
    「BaseStationRegisterContentViewを探す→Flgを確認」の方法は回避して、異なるアプローチを取った方が良いかも知れません。

    アプリケーションの規模であったり、他のコントロールとの絡みなど全体が見えないので、簡単には言えないのですが、
    対象プロジェクトの中で共通してアクセスできるclassを1つ作って(共有変数のような)、その値を参照する。というアプローチの方が単純化できそうです。

    例えば、シンプルに書いてしまいますが
    class 共有変数
    {
    public static bool IsSaved = false; // 終了前に保存が必要か否かの判定に利用
    ....
    }
    # 状況によっては、良い対策と言えない可能性がありますので考慮が必要になりそうです。
    # 既に似たような事例に対して解決する方法が実装されているかも知れませんし、
    # メンバーの方、該当あたりを実装した方に聞く、相談するのが可能であれば
    # それが一番安全と思います。

    キャンセル

  • 2015/09/03 18:35

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

    キャンセル

  • 2015/09/04 11:14 編集

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

    キャンセル

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/03 13:45

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

    キャンセル

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

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    6834questions

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

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