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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

4回答

23477閲覧

複数のコントロールをまとめて値が変更されたかどうか知りたい

ElecDove

総合スコア254

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

1クリップ

投稿2015/11/19 15:27

お世話になります。

VSでC#を使ってWindowsコンソールアプリケーションを作っています。

そのアプリの設定画面なのですが、複数のテキストボックスやラジオボタン等のコントロールがあります。

その画面には「設定を適用する」ボタンがあり、これを押さないと設定が保存されないようになっています。なので、設定を変更したにもかかわらず、このボタンが押されなかった場合、アプリを終了するときなどに「設定が保存されていませんが本当に終了してよろしいですか?」といったダイアログボックスを出したいと思っています。

各々が変更されたかどうかを確認するためにはたとえばTextBoxならTextChangedイベントがあり、それを見れば変更されたかどうかがわかると思います。

ですが、すべてのコントロールで

C#

1 private bool bChanged = false; //変更された場合はフラグがTrue 2 private void textBox_TextChanged(object sender, EventArgs e) 3 { 4 bChanged = true; 5 } 6 7 private void Form_closing(){ 8 if(bChanged){ 9 DialogResult re = MessageBox.Show("本当に終了してもよいですか?",()); 10 } 11 }

などとするのは少々面倒ですし、bChangedフラグを書き忘れればチェック漏れにもなります(もちろんそんなことがあってはいけないのですが・・・)

一応すべてのコントロールはGroupBoxの上に配置されているので、GroupBoxに対してまとめて監視をできたりしないかな、と思ったのですが・・・

よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

ものぐさな方法ですが、

C#

1public Form1() 2{ 3 InitializeComponent(); 4 textBox1.TextChanged += anythingChanged; 5 checkBox1.CheckedChanged += anythingChanged; 6} 7 8private void anythingChanged<T>(object sender,T e) where T : EventArgs 9{ 10 bChanged = true; 11}

とするとanythingChangedは.NETの各種イベントに対応できるので
コントロールが増えてもコンストラクタに1行追加するだけで追加のイベント処理として対応できます。
(なんならプロパティエディタに直接入力して設定もできます。)

ちゃんとそれぞれの値を確認するほうがいいかとは思いますが、、、

投稿2015/11/19 16:56

toki_td

総合スコア2850

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

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

catsforepaw

2015/11/19 21:59

それいいですね。むかーし、別のことでそのようなコードを書いたような記憶がありますが、コントロールの変更イベントと結びつきませんでした。 思い出させてくれてありがとうございます。
ElecDove

2015/11/20 06:07

回答ありがとうございます なるほど! textBox○.TextChanged += anythingChanged; さえ書き忘れなければいいですね笑 しかもこれなら、最終的に値が変更されていなくても、何らかの変更があったことをキャッチできますし、簡単ですし。 今回の件以外にもいろいろと使い道も多そうですし覚えておきたいと思います
guest

0

保存する設定項目をメンバーに持つクラスを定義する
保存されたデータを読み込んでメンバーに保存し、その複製を作る
画面のデータは複製と連動させる(バインドなど)
保存するかどうかのチェック用にそのクラスにメソッドを用意して比較させる
副作用としてリセットボタンで保存データのインスタンスから画面データのインスタンスにディープコピーで実現可能
デメリットはメモリを大目に食うこと
それが嫌な場合はチェックメソッドで保存データを読み込んで比較するように変更し、リセット時も保存データからメンバーのデータを書き換えるようにする
メリットは消費メモリが減るはずだけど、デメリットでメモリ内の比較から保存データ(多分HDDに保存されてる?)の読み込みというコストのかかる処理が追加されること

投稿2015/11/19 15:37

編集2015/11/19 15:42
len_souko

総合スコア1348

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

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

ElecDove

2015/11/20 06:04

回答ありがとうございます >>デメリットはメモリを大目に食うこと なるほど・・・メモリを意識したプログラミングをまだしたことがないので着目点としてそういうのもあるのだなぁ、と勉強になります そこまでメモリを食うわけではなさそうですし、まあそれは妥協してもいいかな、なんて思ってます それよりむしろ、アクセスの遅いHDDから読み込むほうが大変そうです(汗
guest

0

2パターン思いつきました。

1.MVVMのように論理的なクラスを用意してクラスの変更側で検出する。
コントロール(イベント)→クラス(プロパティ)→クラスで変更を検出
2.各コントロールに変更検出の機能を拡張する

1は省略します(MVVM辺りのサンプルモデルはいっぱいあるでしょうし)。
2の場合のイメージは以下の通りです。

C#

1 //変更を検出するためのインターフェイス 2 public interface IChanged 3 { 4 //変更があったかどうかを取得するプロパティ 5 bool IsChanged { get; } 6 //変更状態をクリアする 7 void Clear(); 8 } 9 10 //テキストボックスに実装 11 public class TextBoxEx : TextBox, IChanged 12 { 13 private bool isChanged = false; 14 //実使用上で煩雑にならないように明示的に実装(隠す) 15 bool IChanged.IsChanged 16 { 17 get 18 { 19 return isChanged; 20 } 21 } 22 void IChanged.Clear() 23 { 24 isChanged = false; 25 } 26 27 //変更を検出してフラグをセット 28 protected override void OnTextChanged(EventArgs e) 29 { 30 base.OnTextChanged(e); 31 isChanged = true; 32 } 33 }

このようにTextBoxを拡張しておいて変更を取得するインターフェイスを実装しておきます。
あとはこういう形で調べればいいかと

C#

1 //初期化時 2 foreach(var control in this.Controls.OfType<IChanged>()) 3 { 4 control.Clear(); //コントロールのフラグをリセット 5 } 6 7 //変更を検出したい時 8 var changes = from control in this.Controls.OfType<IChanged>() 9 where control.IsChanged 10 select control; 11 if (changes.Any()) 12 { 13 //どこか変更があった 14 }

ポイントは以下の点です。

・インターフェイスで実現しているので、他のコントロールも同様に実装すればフォーム側は一切手を加える必要がなく拡張に対応できる。
・インターフェイスを明示的に実装させてるので普段TextBoxを使用しているときは拡張分は見えない。

投稿2015/11/19 17:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ベストアンサー

そういう気の利いた機能は聞いたことがありません。
……。

やはり一つ一つイベントを処理するのが王道だと思います。というか、私は今までそうやってきました。
プログラミングというのは面倒な作業なのです。

面倒ですが、その代わり、例えば設定フォームを開いたときに設定内容を覚えておいて、テキストを入力したり、チェックを付けたり外したりするたびに元の情報と照合して、結果的に変更がなければ適用ボタンを無効にする、などということもよくやります。

投稿2015/11/19 15:41

catsforepaw

総合スコア5938

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

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

ElecDove

2015/11/20 06:02 編集

回答ありがとうございます >>その代わり、例えば設定フォームを開いたときに設定内容を覚えておいて、テキストを入力したり、チェックを付けたり外したりするたびに元の情報と照合して、結果的に変更がなければ適用ボタンを無効にする、などということもよくやります。 やはり、これが一番簡単なのでしょうか・・・ >>やはり一つ一つイベントを処理するのが王道だと思います。というか、私は今までそうやってきました。 本当、地味な作業ですね・・・。あるところまで行くと単純作業というかなんというか・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問