トップ回答者
MVVMパターンにおけるエラーチェックの実装方法について

質問
-
いつもお世話になります。
複数のキー項目を画面上で入力し、一致データがあれば
リストに出すような画面をMVVMパターンで作成したいと考えています。その際、項目の桁や、型のチェックを項目単位に行い、
データの存在チェックをボタン押下時に行いたいと考えています。その為、存在チェックはBindingGroupでチェックしているのですが、
上記のようにエラーチェックを行うと
BindingGroupでエラーが発生した場合は項目単位ではなく、BindingGroup
を設定しているエリア自体が赤くなり、項目単位のエラーと見た目が大きく
異なるのが嫌で、回避したいと考えています。そこで質問なのですが、
BindingGroupでエラーが発生した場合は、キー項目だけ赤くしたいのですが
そのような方法はないでしょうか?それとも、そもそもデータ存在チェックも項目単体毎にチェックを行うものなのでしょうか?
項目単位のチェックは入力の度に実行される為、操作性も考えるとボタン押下時のみで
行いたいと考えているのですが、MVVMパターンではそのような実装は行わないものなのでしょうか
回答
-
イメージですが、ボタン押下時に各項目のチェックの呼び出し+DBチェックを行うようなイメージでしょうか。
また、Dictionaryをチェックしてエラーがあるかどうかを返すプロパティを用意し、それによってボタンの有効、無効を切り替えるようにしても良いでしょう。具体的にはDataTriggerでボタンのIsEnabledを制御してやります。ただし、最初の1回目は、エラーチェックを行っていないので本当にエラーがあったとしてもボタンが押せてしまいますが、それはそれで仕様的に問題ないと思います。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク VbBeginer001 2014年3月24日 3:59
すべての返信
-
解決策ではありませんが一点だけ。
> MVVMパターンではそのような実装は行わないものなのでしょうか
MVVMはそもそも概念であって、実装方法を既定するものではありません。今回の質問はむしろMVVMとは関係なく、
> BindingGroupでエラーが発生した場合は、キー項目だけ赤くしたいのですが
そのような方法はないでしょうか?という問題点だけだと思います。
ひらぽん http://d.hatena.ne.jp/hilapon/
- 編集済み ひらぽんModerator 2014年3月17日 6:56 一部修正
-
BindingGroupでエラーが発生した場合は、キー項目だけ赤くしたいのですが
そのような方法はないでしょうか?
Validation.ErrorTemplateに独自のテンプレートをセットすることになると思います。キー項目を赤枠で囲むのであれば、キー項目もそれぞれエラーチェックをするようにするのが簡単でしょう。そうなるとBindingGroupを使う意味が無くなってきますね・・・。ただ、実際のエラーチェックはBindigGroupのエラーチェックのみにし、そのエラー結果を当該の項目にセットするようにする方法もアイデアとしては浮かびます。
ちなみに私はBindingGroupは使わずに、項目を個別にチェックしています。ただ、項目間の相互チェックとなると工夫が必要ですが、不可能なわけではありません。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 星 睦美 2014年3月19日 1:12
-
trapemiyaさん、ご回答ありがとうございます。
「実際のエラーチェックはBindigGroupのエラーチェックとする 」というのがあまりぴんとこないのですが、
CommandのCanExecuteの中でBindigGroup内のチェック処理を呼び出すイメージでしょうか?
項目間の相互チェックまでなら、各項目のチェックの中でいけそうな事はないのですが、
テキストボックスはUpdateSourceTrigger=PropertyChangedで、入力の度にチェック処理を走らせているので
DBとやり取りするチェックはレスポンスを考えると、入れたくないので
なんとかBindigGroupのエラーを使用する方法を模索したいと思います。
-
「実際のエラーチェックはBindigGroupのエラーチェックとする 」というのがあまりぴんとこないのですが、
CommandのCanExecuteの中でBindigGroup内のチェック処理を呼び出すイメージでしょうか?
いえ、そうではなくて、Validateをoverrideしたメソッド内でエラーチェックを行い、エラーになった場合は、IDataErrorInfoでエラーになるようにその項目を設定するということです。
基本的には、以下のページのイメージになりますが、各項目のエラーチェックを各項目のプロパティで行わず、Validateをoverrideしたメソッド内で行うということです。そのためには少し工夫が必要で、Dictionaryで各プロパティのエラー文字列を管理するようにし、
IDataErrorInfoのメンバーであるpublic string this[string columnName]は、このDictionaryからエラー文字列を返すようにすると良いでしょう。Using BindingGroups for greater control over input validation
http://www.scottlogic.com/blog/2008/11/28/using-bindinggroups-for-greater-control-over-input-validation.html
項目間の相互チェックまでなら、各項目のチェックの中でいけそうな事はないのですが、
テキストボックスはUpdateSourceTrigger=PropertyChangedで、入力の度にチェック処理を走らせているので
DBとやり取りするチェックはレスポンスを考えると、入れたくないので
なんとかBindigGroupのエラーを使用する方法を模索したいと思います。
最初に、
>データの存在チェックをボタン押下時に行いたいと考えています。>その為、存在チェックはBindingGroupでチェックしているのですが、
と書かれているのですが、こことの整合性はどのようになるのでしょうか?
また、各項目間で相互にチェックし合えば、それはDBとやり取するチェックになるわけではないのですが、どのようなことを懸念されているのでしょうか? この辺りがよくわかりませんでした。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
trapemiyaさんご回答ありがとうございます。
サイトは今目を通したばかりなので、是非参考にしたいと思います。
すみません、私の回答内での相互チェックはDBにアクセスしない項目の相互チェック
という認識で記載していました。(A・Bという項目があった場合、Bを入力した場合にAの項目が入力されているか、
型が可能な型か等のチェック)
私のやりたいと考えている内容は下記のような流れを想定しています。
・画面に複数の項目がある
・項目毎の整合性チェックは各項目入力時に行う
・入力終了後・ボタン押下時にDBのデータ存在チェックを行う
・データが無い場合は、キー項目を赤色に変更する
日本語が不自由で申し訳ありません
-
この場合、BindingGroupを使わない方が見通しが良くなるような気がします。
各項目のプロパティのSetterから、その項目のエラーチェックを行うようにします。必要があれば他の項目との関連性のチェックも行います。
エラーの結果は先に述べたようにDictionaryで管理し、IDataErrorInfoのメンバーであるpublic string this[string columnName]は、このDictionaryからエラー文字列を返すようにします。Dictionaryで管理していますから、今チェックしている項目以外の項目にエラー文字列をセットすることは、とても簡単なことです。>・入力終了後・ボタン押下時にDBのデータ存在チェックを行う
この前に、全項目のチェックを一度行うべきでしょう。なぜなら、人が入力していない項目は一度もエラーチェックが行われないからです。
実際、私は上記の方法で実装を行うことが多いです。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 星 睦美 2014年3月20日 7:51
-
この場合、BindingGroupを使わない方が見通しが良くなるような気がします。
各項目のプロパティのSetterから、その項目のエラーチェックを行うようにします。必要があれば他の項目との関連性のチェックも行います。
エラーの結果は先に述べたようにDictionaryで管理し、IDataErrorInfoのメンバーであるpublic string this[string columnName]は、このDictionaryからエラー文字列を返すようにします。Dictionaryで管理していますから、今チェックしている項目以外の項目にエラー文字列をセットすることは、とても簡単なことです。>・入力終了後・ボタン押下時にDBのデータ存在チェックを行う
この前に、全項目のチェックを一度行うべきでしょう。なぜなら、人が入力していない項目は一度もエラーチェックが行われないからです。
実際、私は上記の方法で実装を行うことが多いです。
私も trapemiya さんとほぼ同じ実装です。唯一上記と違うのは、項目に有効値が入力されてない場合はコマンドを実行できないよう、各プロパティのSetter でコマンドが実行可能か検証してることくらいですね。もっともこの辺りの実装は設計にもよるでしょうが・・・
#というわけで BindingGroup は使ったことがないです。
ひらぽん http://d.hatena.ne.jp/hilapon/
- 編集済み ひらぽんModerator 2014年3月19日 7:04 誤字修正
-
イメージですが、ボタン押下時に各項目のチェックの呼び出し+DBチェックを行うようなイメージでしょうか。
また、Dictionaryをチェックしてエラーがあるかどうかを返すプロパティを用意し、それによってボタンの有効、無効を切り替えるようにしても良いでしょう。具体的にはDataTriggerでボタンのIsEnabledを制御してやります。ただし、最初の1回目は、エラーチェックを行っていないので本当にエラーがあったとしてもボタンが押せてしまいますが、それはそれで仕様的に問題ないと思います。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク VbBeginer001 2014年3月24日 3:59