- PR -

[VB2005] Validating イベント内で MsgBox を使えないジレンマ

投稿者投稿内容
こばさん
大ベテラン
会議室デビュー日: 2004/03/17
投稿数: 147
投稿日時: 2007-12-03 16:00
 もの凄く初歩的なところなんですが

Private Sub HogeHoge_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles HogeHoge.Validating
   If MsgBox("いいの?", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
     e.Cancel = True
   End If
End Sub

 こういうのが NG というのは散々既出ですが、Validating の中でフォーカス遷移を伴うことが出来ない、って皆さんどうやって回避してますか?
 Validating を引き起こす相手がボタンと決まってれば、ActiveControl を見つけ出して PerformClick() すればいいかもしれませんが、引き起こす相手の種類と動作の数だけ Perform〜 なんて書きたくありませんし、全く美しくありません。
(全部を網羅なんて不可能)

 e.Cancel = False の時は、Validating の中で起きたフォーカス遷移のことは無かったことにして、当初予定していたイベント順序で中の人が仕事をしてほしいところですが。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-12-03 20:43
引用:

こばさんさんの書き込み (2007-12-03 16:00) より:

こういうのが NG というのは散々既出ですが、


そうなのですか? であらばリンクで示してください。

引用:

Validating の中でフォーカス遷移を伴うことが出来ない、って皆さんどうやって回避してますか?


キャンセルしたとき限定のお話ですか?

引用:

Validating を引き起こす相手がボタンと決まってれば、ActiveControl を見つけ出して PerformClick() すればいいかもしれませんが、引き起こす相手の種類と動作の数だけ Perform〜 なんて書きたくありませんし、全く美しくありません。
(全部を網羅なんて不可能)


この場合どうしたいと願っていますか?

実は所望している内容が 100% 理解できていませんが、たぶん回避方法もそれなりに既出だったような気がします。 Jitta さんは CauseValidation + α 派だったような気がします。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-12-04 07:39
あれ?名前が出てる

タイトルには興味を持ったのですが、昨日は忙しくてチェックする時間をとれませんでした
今、携帯で見ているのですが、何をしたいのかわかりません。
Validating イベントはフォーカス遷移の一環として発生します。あるコントロールから別のコントロールへ遷移する途中に発生するのに、それをさらに別のコントロールへ横取りさせるという動作がおかしいと思います。

なんとなく、ボタンをクリックしたときに「いいの?」と出して、よかったらボタンを押した処理を走らせよう、ダメならフォーカスを移さないでおこう、という処理だと思われます。そうであれば、Validating イベントでメッセージを出すのではなく、ボタンのクリック イベントで出すべきでしょう。画面上に入力コントロールが複数あれば、全部の Validating イベントにメッセージを書くのでしょうか?それこそナンセンスだと思います。
こばさん
大ベテラン
会議室デビュー日: 2004/03/17
投稿数: 147
投稿日時: 2007-12-04 11:00
 例えば、Button を押したことで 先ほどの HogeHoge.Validating に引っかかり「いいの?」に「いいよ(OK)」をクリックしたときは、e.Cancel = False のままなので、ボタンの Button.Click の中に書いた続きをやってくれたらなぁ〜と期待しちゃってるだけの話なんです。

 Validating の中でフォーカスを奪うと e.Cancel = False であっても Button.Click の動作が行われないんですよね。
 フォーカスは Button に移ってるのに。

 Button.Click の動作を続けるためには Validating の中で Button.PerformClick() しないといけない。
 外部コントロールの動作を定義しないといけないというということに不自然に感じるのです。

※ e.Cancel = True のときは何ら問題ありませんけど。


 Validating の中で MsgBox を開いた場合でも e.Cancel = False にしてイベントから抜ければ、他の動作に影響しない(「MsgBoxでフォーカス遷移がなされた」ということがなかったことにしてくれる)動作だとプログラマに優しいのに・・・と思いませんか?
(仕様と割り切らないといけない今の動きに残念な思い)
 
 項目の評価はボタンの Click じゃなくて、評価対象のコントロール自身が自分の Validating の中で書いた方が美しいと思ってる人なので・・・
(その評価の中で、ユーザーの判断を仰ぐ曖昧さも許容したい)

※ ここで解決法を求めているんじゃなくて愚痴モードです
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-12-04 11:57
引用:

 Validating の中で MsgBox を開いた場合でも e.Cancel = False にしてイベントから抜ければ、他の動作に影響しない(「MsgBoxでフォーカス遷移がなされた」ということがなかったことにしてくれる)動作だとプログラマに優しいのに・・・と思いませんか?


全く思いません。

WindowsにおけるGUIのデザイン・スタイルを理解する必要があります。
そうすればValidateの意味がわかるはずです。

Windowsにおいては、入力には「ダイアログ」という窓を用いることになっています。
ダイアログはOKを押したときに情報が確定します。
ユーザーにYes/Noを確認すべきなのはこの時点です。

ValidateはFocusを移してよいかの検証に用いるもので、
文字数が多すぎるとか、入力できない文字が入ってるとか、
そういった明らかな間違いを防ぐためのものです。
Validateではユーザーに入力を求めるべきでないデザインになっているわけです。

引用:

 項目の評価はボタンの Click じゃなくて、評価対象のコントロール自身が自分の Validating の中で書いた方が美しいと思ってる人なので・・・


Windowsでは、ダイアログ毎に情報を確定することになっていて、
コントロール毎にユーザーに確認するものではありません。
これは煩雑だからという考えがあります。

そこまできちんと理解しているなら、
> ※ ここで解決法を求めているんじゃなくて愚痴モードです
批判すべきはValidateの実装ではなくWindowsのGUIデザインです。

#ちなみに。
#WindowsのGUIにはいろいろ問題がありますが、
#私はこの部分は批判的ではありません。

お勧めしませんが、
コントロール毎にValidateの様なことをするのも可能です。
自分で簡単に実装できます。

ですが、「オレデザイン」なGUIでやると
ユーザーは普段と違うインターフェースを学習しないといけません。
自分で実装するコードも増えます。
その分のコストに見合うリターンがあるなら別にいいと思いますが、
普通はないです。


[ メッセージ編集済み 編集者: れい 編集日時 2007-12-04 12:03 ]
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-12-04 12:00
引用:

Validating の中で MsgBox を開いた場合でも e.Cancel = False にしてイベントから抜ければ、他の動作に影響しない(「MsgBoxでフォーカス遷移がなされた」ということがなかったことにしてくれる)動作だとプログラマに優しいのに・・・と思いませんか?
(仕様と割り切らないといけない今の動きに残念な思い)



OSの根底の概念を覆すことになるので無理でしょうね。
(Validatingに限らず)割り切るんじゃなくて、
フォーカス系メッセージの連鎖内で(メッセージが途切れる)モーダルダイアログなどを表示させると
意図せぬ結果になるという理解をしたほうがよいです。

引用:
 
(その評価の中で、ユーザーの判断を仰ぐ曖昧さも許容したい)



フォーカスの移動=ユーザーの判断、つまり、フォーカスの移動=ダイアログの「はい」と理解して
Validatingではユーザーの判断を仰ぐ以前の大前提のチェックだけにするとか。
結局最終ボタンなりで確認するはずですし、項目ごとにダイアログが出るとうっとうしいと苦情を言うユーザーも出てくるのではないかと。
こばさん
大ベテラン
会議室デビュー日: 2004/03/17
投稿数: 147
投稿日時: 2007-12-04 12:56
>項目ごとにダイアログが出るとうっとうしいと苦情を言うユーザー

 項目毎にダイアログを出せ、というですよ
 たとえば、0〜100 の範囲で入力しないといけない場合に、範囲外は「0〜100の範囲で入力してくださいよ!」的なダイアログ(e.Cancel = True)を出せ、というですよ。
 更に80以上だったら「え?本当に80以上なの、すごいね!」みたいなダイアログ(e.Cancel = False)で御節介を焼いて欲しいそうな。

 こんなのが画面に数十あったら、Validating の中でやりたいと思ってしまいます。
(Validating の中だけMsgBox使用に伴うフォーカス遷移が蚊帳の外になってくれれば・・・と切に思うわけです)


>Validateではユーザーに入力を求めるべきでないデザインになっているわけです。

 この1文に尽きますね・・・
 それだったら Validating なんていうイベント名じゃなくて、BeforeLeave とかだったら全く未練ないのですが。「Validate」という名前だったらユーザーに入力を求める評価にも使いたくなってしまう。。


 HogeHoge.Validating の中で e.Cancel = True にしても、移動予定先の Enter イベントは発生するくせに Leave は起きないし・・・(Enterを起こすならLeaveも起こせよ〜)
↑ Validating の中で MsgBox を使ったとき

 Validateではユーザーに入力を求めるべきでない・・・そういうことなんですよねぇ
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-12-04 13:09
引用:

それだったら Validating なんていうイベント名じゃなくて、BeforeLeave とかだったら全く未練ないのですが。「Validate」という名前だったらユーザーに入力を求める評価にも使いたくなってしまう。。


その辺は感覚の問題でしょう。

確認や検証という意味でよく使われる単語には
Check Confirm Validate Verify Endorse
などがありますが、
Confirmならユーザー入力があってもいい気が私はします。

Validateには「妥当である」という意味がありますから、
適切な名称だと私は思います。

スキルアップ/キャリアアップ(JOB@IT)