タブページについて への返答

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

投稿者   () 投稿日時 2008/8/14 17:44:00
>>6 
SelectedIndexChangedなんてイベントがあったとは・・・ 
知りませんでした。 
 
ValidatingやLeaveしか頭になかったのですが、 
確かにこちらのほうが簡単かもしれませんね。
投稿者 るしぇ  () 投稿日時 2008/8/12 21:18:00
Private Sub TabPage_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) _ 
                Handles TabPage1.Validating, TabPage2.Validating 
  ''※注 Validating イベントをキャンセルするので下のコードでは対応できない 
  ''▼Formを閉じるときにはイベントが発生しないようにする  
  'If ActiveControl.CausesValidation = False Then 
  '  Exit Sub 
  'End If 
 
  Dim targetTab As TabPage 
  targetTab = DirectCast(sender, TabPage) 
 
  '▼検証中の TabPage の全てのコントロールに対し、TextBox であれば入力チェック 
  For Each t As Control In targetTab.Controls 
    If TypeOf t Is TextBox AndAlso 自作メソッド(t.Text) = False Then 
      e.Cancel = True 
      't.Focus() 
      DirectCast(t, TextBox).SelectAll() 
      Exit Sub 
    End If 
  Next 
End Sub 
 
'■自作メソッド  
''' <summary>指定した値が正しいかチェックする</summary>  
''' <param name="Expression">チェックしたい文字列型の値</param>  
''' <returns>正しければTrueを返し、エラーならメッセージを表示してFalseを返す</returns>  
Private Function 自作メソッド(ByVal Expression As String) As Boolean 
 
  Dim reg As New System.Text.RegularExpressions.Regex("^\d{1,3}$") 
 
  If Not reg.IsMatch(Expression) Then 
    MsgBox("error", vbCritical, "入力エラー") 
    'TabControl1.SelectedIndex = 0 
    Return False 
  End If 
 
  If CInt(Expression) > 300 Then 
    MsgBox("300over", vbCritical, "入力エラー") 
    'TabControl1.SelectedIndex = 0 
    Return False 
  End If 
 
  Return True 
End Function
投稿者 るしぇ  () 投稿日時 2008/8/12 21:17:00
>>5 
>また、このコードだとFocusのところでValidatingイベントが  
>発生してしまい、メッセージが2回表示されてしまいます。  
Validating 使うときは e.Cancel を使うべきと思うんだけど、検証イベントから 
抜ける手段を用意しないと Form を閉じることができませんね。 
# まぁ、検証イベントをクリアしてないんだから、正しい動きでもあるんでしょうが。 
 
そうなってくると一度検証したテキストボックスについては Text が変更されるまで 
再検証しないようなコードも欲しくなってきます。。。ところが、ここで複数の 
テキストボックスがあるとフラグも複数必要?。。。と深みにハマってくのでボクは 
Validating が嫌いですww 
 
初心者は前回選択されていたタブを変数に覚えてて、TabControl1.SelectedIndexChanged 
使うほうが簡単かも?ま、とりあえずボクは Validating を使いこなせてないので、1つの 
案だけにとどめます。
投稿者   () 投稿日時 2008/8/12 18:54:00
    Private Sub TabPage1_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TabPage1.Validating 
        '▼Formを閉じるときにはイベントが発生しないようにする 
        If ActiveControl.CausesValidation = False Then 
            Exit Sub 
        End If 
 
        '▼TabPage1の全てのコントロールに対し、入力チェック 
        For Each t As TextBox In TabPage1.Controls 
            If 自作メソッド(t.Text) = False Then 
 
                t.Focus() 
                t.SelectAll() 
                Exit Sub 
            End If 
        Next 
    End Sub 
 
    '■自作メソッド 
    ''' <summary>指定した値が正しいかチェックする</summary> 
    ''' <param name="Expression">チェックしたい文字列型の値</param> 
    ''' <returns>正しければTrueを返し、エラーならメッセージを表示してFalseを返す</returns> 
    Private Function 自作メソッド(ByVal Expression As String) As Boolean 
 
        Dim reg As New System.Text.RegularExpressions.Regex("^\d{1,3}$") 
 
        If Not reg.IsMatch(Expression) Then 
            MsgBox("error", vbCritical, "入力エラー") 
            TabControl1.SelectedIndex = 0 
            Return False 
        End If 
 
        If CInt(Expression) > 300 Then 
            MsgBox("300over", vbCritical, "入力エラー") 
            TabControl1.SelectedIndex = 0 
            Return False 
        End If 
 
        Return True 
    End Function 
 
入力チェックならエラーのときはテキストを初期化する 
より、全て選択したほうが親切かと思い、SelectAllを 
使用しています。 
 
また、このコードだとFocusのところでValidatingイベントが 
発生してしまい、メッセージが2回表示されてしまいます。 
他に方法はないものでしょうか・・・・・ 
他の方のフォローに期待します^^;
投稿者   () 投稿日時 2008/8/12 18:52:00
>サンプルプログラムとして、タブページ2つに、 
>各タブページの中にTextBoxが2つずつある画面で 
↑のことからTextBox2もTabPage1上に存在するものだと 
解釈しました。 
 
>そうはせずに、処理を纏めて、プロシージャに呼び出す?方法があると聞きました。 
処理を纏めて、プロシージャに呼び出すというのは 
よく分かりませんでした、未熟ですみません。 
処理を纏めたメソッドを自作するということでしょうか? 
 
とりあえず入力チェックしてエラーならFocusを戻す。 
というコードを考えてみました。 
イベントをValidatingに変更してあります。 
また、Formを閉じるときにもチェックがかかってしまう 
のでFormのCausesValidationプロパティをFalseにして 
おいてください。 
 
長くなるのでコード部分は分けて投稿します。
投稿者 らるきー  () 投稿日時 2008/8/11 21:11:00
>>1 鍵さん 
お返事ありがとうございます! 
VB2005を使用しています。 
 
変な日本語で申し訳なかったですが、アドバイス頂いた様にしてみるとできました↓ 
サンプルプログラムとして、タブページ2つに、各タブページの中にTextBoxが2つずつある画面で 
 
 Dim i, p, x, y As Integer 
 
 Private Sub TabPage1_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TabPage1.Leave 
 
         
    '正規表現で入力された値を判断する。 
    If Regex.IsMatch(TextBox1.Text, "^[0-9]{1,3}$") Then 
            i = Val(TextBox1.Text) 
            i = Convert.ToInt32(i) 
        Else 
            MsgBox("textbox1 error", vbCritical, "入力エラー") 
            TextBox1.Clear() 
 
            Exit Sub 
        End If 
        Me.TextBox1.Focus() 
 
        If i > 300 Then 
            MsgBox("300overr", vbCritical, "入力エラー") 
            TextBox1.Clear() 
            Exit Sub 
        End If 
        Me.TextBox1.Focus() 
    End Sub 
 
これでtabpage1のTextBox1に入力された数値を、TabPage1以外のTabPageに移ろうとしたときに、 
判断できるようになりましたが。。 
 
>たとえば、[OK]ボタンがクリックされたときにまだ必要な項目、たとえばメールアドレスが入力されていなかったとします。 
>この場合にただ単に「メールアドレスを入力してください。」という警告のメッセージを表示するだけではなく、 
>そのメッセージとともに自動的にメールアドレス欄がフォーカス状態になるならば、 
>それは親切なアプリケーションと言えます。 
 
とこちらのサイトでも仰られている様に、エラーがあった箇所にフォーカスを戻したいのですが 
↑のプログラムではTabPage1以外に移った場合、そのTabPageのTextBoxにフォーカスが移ってしまいます。。 
何とかTabPage1に戻って、エラーのあるTextBoxにフォーカスを戻す方法はないでしょうか? 
 
それともう1つなのですが、↑のプログラムはTabPage1のTextBox1の処理なのですが 
もう1つTextBox2にも同じ処理をさせたいので、コピーすれば早いのですが。。 
そうはせずに、処理を纏めて、プロシージャに呼び出す?方法があると聞きました。 
 
なにぶん初心者でよくわかっていないのですが、そちらの方法もご教授いただければと思います。 
長々と本当にすみません!
投稿者   () 投稿日時 2008/8/11 16:38:00
こんにちは。 
 
問題の早期解決の為にも、VBのバージョンの明記を 
お願いします。 
 
とりあえず以下のように解釈しましたが、 
よろしいでしょうか? 
 
タブページ1~3にTextboxが1つずつ配置されている。 
 
Buttonを押したときに表示されているページの 
TextboxのTextが数字か判断する。 
 
表示されているタブページが1でなくなったときに 
Textbox1のTextが数字か判断する。 
 
表示されているタブページはTabControl.SelectedIndexで 
知ることができます。 
また、数字かどうかはIsNumericで判断できます。 
 
以下がコードです。(VB2008)で検証、動作確認。 
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
        Select Case TabControl1.SelectedIndex 
            Case 0 
                Judge(TextBox1.Text) 
            Case 1 
                Judge(TextBox2.Text) 
            Case 2 
                Judge(TextBox3.Text) 
        End Select 
 
    End Sub 
 
    Private Sub TabPage1_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TabPage1.Leave 
        Judge(TextBox1.Text) 
    End Sub 
 
    Private Sub Judge(ByVal Expression As String) 
        If IsNumeric(Expression) Then 
            '数字だったときの処理を書く 
            MsgBox("数字です") 
        Else 
            '数字ではないときの処理を書く 
            MsgBox("数字ではありません") 
        End If 
    End Sub 
 
意図した動作でなかったらすみません。
投稿者 らるきー  () 投稿日時 2008/8/11 08:30:00
何やら掲示板が大変なこと?になっている時に失礼致します。。 
2ヶ月ほど前からvb.netを触り始めた初心者です。 
いつもこちらのサイトを参考にさせて頂いております。 
 
現在タブページを使用したデザインのプログラムをしていますが、タブページ1~3に配意されたTextBoxの内容をボタンが押されたときに数字かどうかの判断をする処理を書いているのですが、 
 
タブページ1に配置されたTextbox1の入力内容を、ほかのタブページに移動する際(タブページ2、または3を選択したとき)に処理の命令を出すようにしたいのです。 
 
文章が下手で上手く伝わるかどうかわかりませんが 
アドバイスよろしくお願いいたします><