ValidatingとLeaveについて。

タグの編集
投稿者 まる  (社会人) 投稿日時 2009/1/30 00:52:14
はじめまして。最近VB.NETでプログラマになったばかりのまると申します。

いきなりですが、会社からだされた練習問題でつまづいています・・・。
ご教授お願いいたします。

問題はこちらです。

テキストボックスが10個あります。(TextBox1~10)
テキストボックスに文字列をいれます。
①入力し終わって、他のコントロールに移るとエラーか判断します。
そのとき、もしそのテキストボックスの文字列のバイト数が11以上なら、エラーメッセージ表示。
また、なにも入っていなくてもエラーメッセージ表示。

ここからが自分がぶつかっているところなんです・・・。

今アクティブになっているテキストボックスより数字が高いTextBox(アクティブがTextBox5なら、TextBox6以上)にフォーカスが移るときは、エラー判断だけ。
②今アクティブになっているテキストボックスより数字が低いTextBox(アクティブがTextBox5なら、TextBox4以下)にフォーカスがいかないようにする。そのときも、アクティブなテキストボックスのエラー判断をする。
「前項目」ボタン(Button1)が押された時は、アクティブになっているテキストボックスの1つ前にフォーカスを移す(アクティブがTextBox5なら、TextBox4に)。そのときも、アクティブなテキストボックスのエラー判断をする。

今自分は、
TextBox1~10.Validatedメソッド で、①のエラー判断、
TextBox1~10.Validatingメソッド で、②になるような操作をしています。

今の状態だと、「前項目」ボタンや、フォームを閉じるためのボタン(Button2)もききません。ブレークポイントで試してみても、ボタンが押されていない状態になっています。
ちなみにテキストボックスのタグにそれぞれのテキストボックスの数字が入っています。

説明が不足していたらすみません。よろしくお願いいたします。

Dim ActiveTag As Integer = 1 'アクティブなテキストボックスの取得に使っています。
Dim CmpTag As Integer = 1 'テキストボックスの比較に使っています。

    Private Sub TextMove(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _
                TextBox1.Validated, TextBox2.Validated, TextBox3.Validated, TextBox4.Validated, _
                TextBox5.Validated, TextBox6.Validated, TextBox7.Validated, TextBox8.Validated, _
                TextBox9.Validated, TextBox10.Validated

        Dim SJIS As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
        Dim textname As String

        If ActiveControl.CausesValidation = False Then
            Exit Sub
        End If


        textname = "TextBox" + CStr(ActiveTag)

    'テキストボックスの中身がバイト数11以上だったら
        If SJIS.GetByteCount(Me.Controls(textname).Text) > 10 Then

            MsgBox(CStr(ActiveTag) + "番目の文字が長すぎます。", MsgBoxStyle.Critical, "確認")

            Me.Controls(textname).Focus()

    'テキストボックスの中身が何もなければ
        ElseIf SJIS.GetByteCount(Me.Controls(textname).Text) = 0 Then

            MsgBox(CStr(ActiveTag) + "番目に文字が入力されていません。", MsgBoxStyle.Critical, "確認")

            Me.Controls(textname).Focus()

        End If

        ActiveTag = CInt(ActiveControl.Tag)

    End Sub

    Private Sub TextValidating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles _
    TextBox1.Validating, TextBox2.Validating, TextBox3.Validating, TextBox4.Validating, TextBox5.Validating, _
    TextBox6.Validating, TextBox7.Validating, TextBox8.Validating, TextBox9.Validating, TextBox10.Validating

        If ActiveControl.CausesValidation = False Then
            Exit Sub
        End If

        CmpTag = CInt(ActiveControl.Tag)

    '直前にアクティブだったテキストボックスと、次に選択されたテキストボックスの比較
        If ActiveTag > CmpTag Then

            e.Cancel = True

        End If

    End Sub
投稿者 まる  (社会人) 投稿日時 2009/1/30 01:04:37
タイトルの理由は、ValidatingとLeaveのどちらでプログラミングすればいいかという意味です。
何も理由書かずにすみません。
投稿者 刈谷勇  (社会人) 投稿日時 2009/1/30 01:40:50
はじめまして、まるさん。


えーと、まず気づいた点から。
現在のTextBox取得するのに名前を使用していますが、こだとあとあと別の人が名前を変えてしまうとプログラムが動かなくなってしまいます。ActiveControlプロパティを調べてみてください。また、各オブジェクトの名前はたとえば、閉じるボタンならbtCloseのような誰でもそのオブジェクトの意味がわかるような名前にしておくといいですよ。

あと、質問点の回答ではなくヒントを
>ValidatingとLeaveのどちらでプログラミングすればいいかという意味です。
これはValidatingでいいと思います。別の私が投稿した質問でnさんも回答してくださっていますが、Validatingは入力値のチェックを行う為のイベントです。Leaveはそのオブジェクトからカーソルが移るときのイベントです。

ただ、Validated/Validatingイベントはいろいろなかせられます。
(この辺はプログラムを書いていけばわかると思います。)



>今の状態だと、「前項目」ボタンや、フォームを閉じるためのボタン(Button2)もききません。ブレークポイントで試してみても、ボタンが押されていない状態になっています。

これはValidatingイベントが動いてしまっている性だと思います。
この辺の話題は、ここの管理人さんが初級講座の「第23回 コントロールの遷移制御」で取り上げられていますので参考にしてみてください。
(多分、「Validated/Validatingイベントはいろいろなかせられます。」の意味が少しわかると思います。)
投稿者 まる  (社会人) 投稿日時 2009/1/30 22:01:22
刈谷勇さん、お返事ありがとうございます。

今日一応直してみました。
ValidatedとValidatingで、どうにかボタンもきくようにはなりました。

しかし、今度は
If SJIS.GetByteCount(Me.Controls(textname).Text) Then
の部分で、
1つ以上飛ばして(TextBox1→TextBox3など)、確認ボタンを2回押すと
1回目はエラー表示されて、問題個所にフォーカスがうつるのですが、2回目だと
「オブジェクト参照がオブジェクト インスタンスに設定されていません。」
とでてしまいます。

これはテキストボックスをNewすればいいのですか・・・?
投稿者 まる  (社会人) 投稿日時 2009/1/30 23:55:48
何度もすみません。

原因はテキストボックスの場所がわからなくなってしまうエラーでした。
アクティブコントロールでやろうと思ったのですが、Validatingにかくと、
TextBox1→TextBox2にすると「2番目のテキストボックスが入力されていません。」
と、今入力したところではなく、フォーカスを移動したところの比較をしてしまうのです。
Validatedにしてもおなじでした。

何かいい方法はないのでしょうか・・・?
投稿者 刈谷勇  (社会人) 投稿日時 2009/1/31 03:23:39
>アクティブコントロールでやろうと思ったのですが、Validatingにかくと、
>TextBox1→TextBox2にすると「2番目のテキストボックスが入力されていません。」
>と、今入力したところではなく、フォーカスを移動したところの比較をしてしまうのです。

すみません、テストしないで投稿してしまいました。


では、senderを使ってみてください。ただし、senderはobject型なので型変換が必用です。
型変換については、
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard36.htm
を見てください。
(すいません、今回も未テストですので問題があったらまた書き込んでください)
投稿者 まる  (社会人) 投稿日時 2009/2/2 19:13:44
刈谷勇さん、またまた回答ありがとうございます。
お返事遅れてすみません。

少し話がずれるんですけど、質問してよろしいでしょうか?

TextBoxの中身をArrayListに追加して、ArrayListの中身をLabelに移したいと思っているんです。
中身が入っていれば問題はないのですが、TextBoxが何もない状態でArrayListに追加してLabelに表示しようとすると、
「ArgumentOutOfRangeExceptionはハンドルされませんでした。」
「インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。」
とでて、エラーになってしまいます。

どうにかしてArrayListの中身がないときの比較をしたいのですが、
その比較の時点で同じエラーになってしまいます。

CStr(Ar(0))で型変換して比較しているのですが、それがいけないんでしょうか?

調べてみたのですが、まったくわかりません・・・。
よろしければご教授お願いいたします。
投稿者 刈谷勇  (社会人) 投稿日時 2009/2/2 20:27:45
まるさん
とりあえず表題と関係ないので、別スレにしてください。
回答はそちらにつけますので
投稿者 まる  (社会人) 投稿日時 2009/2/2 20:56:51
題名に関係ない質問をしてしまってすみません。いま別にスレッドを作成しました。