none
Validatingイベントでキャンセルしてもデータセットに更新される RRS feed

  • 質問

  •  

    DataSourceUpdateModeがOnValidationの状態で、TextBoxのValidatingイベントでキャンセルしたのですが、値が更新されてしまいました。

     

    以下が行ったことです。

    ・新規WindowsApplication1を作成
    ・DataSet1を作成
    ・Column1(Int32)を持つDataTable1を作成
    ・Form1にデータソースウィンドウから「詳細」でDataTable1をドラッグ&ドロップする
    ・Form1にツールバーからTextBoxをドラッグ&ドロップする(Column1TextBoxのValidationを起こすため)
    ・Form1にツールバーからButton1をドラッグ&ドロップする
    ・Form1.vbに以下のコードを貼り付け (処理概要:3文字以上の入力をはじく)

     

    Code Snippet

    Public Class Form1

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.Button1.CausesValidation = False
        End Sub

        Private Sub Column1TextBox_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles Column1TextBox.Validating
            Dim tb As TextBox = CType(sender, TextBox)
            If tb.Text <> "" Then
                If Len(tb.Text) > 2 Then
                    MsgBox("形式エラー")
                    e.Cancel = True
                End If
            End If
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            MsgBox("Column1:'" & CType(Me.DataTable1BindingSource.Current, DataRowView).Row("Column1").ToString & "'")
        End Sub

    End Class

     

     

    ・実行
    ①レコード追加(+)ボタンを押す→テキストボックスに「aaa」と入力し、TABキーを押す→「形式エラー」と出る→Button1を押す→「Column1:''」と出る

    ・一旦終了し、再度実行
    ②レコード追加(+)ボタンを押す→テキストボックスに「111」と入力し、TABキーを押す→「形式エラー」と出る→Button1を押す→「Column1:'111'」と出る


    「111」と入力し形式エラーとなった場合、Button1を押すと「Column1:''」となることを希望していました。コードのどこかが悪さをしているのでしょうか?

     

    ちなみに
    ・DataSourceUpdateModeはデフォルトのOnValidationになっています。
    ・ComboBoxに変えてみても同様でした。

    また、
    舞台裏で: .NET Framework 2.0 における Windows フォーム データ バインドの改良点 (第 1 部)
    http://www.microsoft.com/japan/msdn/net/winforms/wfbindp1.aspx

    DataSourceUpdateMode を使用する
    を読むと、
    「…、値が検証に合格すると更新されます。」
    と書いてありました。
    この「検証」の意味を私は「TextBox.Validating内で e.Cancel = True とされたかどうか」を含む、と捉えていました。
    従って、「111」と入力してValidationでキャンセル(e.Cancel = True)されると更新されないと思っていました。

     

    とりあえずこの影響が出ないようにプログラムの作り方を変えたのですが、気になっておりまして、ご教示頂ければ幸いです。

     

    環境:

    Microsoft Visual Studio 2005 Version 8.0.50727.42  (RTM.050727-4200)
    Microsoft .NET Framework Version 2.0.50727

    インストールされている Edition: VB Express

    Windows Vista Business

    2007年9月8日 5:12

すべての返信

  • ひょっとして、「…、値が検証に合格すると更新されます。」の「検証」って、TextBox.Validationイベントとは無関係だっただけ、という話でしょうか?
    投稿してから何となくそんな気が…(ノ_<。)

    でも裏付けとなる資料が見つからない…

    2007年9月8日 5:35
  •  

    1つリンクと引用を忘れていたので補足します。

     

    DataSourceUpdateMode 列挙体
    http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.datasourceupdatemode(VS.80).aspx

     

    OnValidation
    コントロール プロパティが検証されると、データ ソースが更新されます。 
    検証後、コントロール プロパティの値の書式も再設定されます。

    2007年9月8日 5:50
  •  

    自己レスばかりですみません。
    投稿する前にもちっと考えるべきだったと激しく後悔orz。

    でもわかったことがあるのでスレを更新しておきます。

     

    さて、Column1をInt32からStringに変更してみると、①でもColumn1:'aaa'と表示されました。
    従って、やはりColumn1TextBox.Validatingでのe.Cancelは
    「…、値が検証に合格すると更新されます。」
    で言う「検証」とは無関係だと思いました。

     

    ではいったいこの「検証」とは何のこと?と思い、とりあえずこの「検証」を失敗させる方法を見つけることで解明しようと考えました。

    そこで今度はDataSet側の検証に関係ありそうな情報を探し、

     

    方法 : 列の変更時にデータを検証する
    http://msdn2.microsoft.com/ja-jp/library/0f7ey06d(VS.80).aspx

    「・列変更イベント ハンドラで列エラー (SetColumnError) を設定して、指定された値を拒否します。」

    とあるのを見つけました。ここのサンプルコードにある

     

    DataRow.SetColumnError メソッド (DataColumn, String)
    http://msdn2.microsoft.com/ja-jp/library/system.data.datarow.setcolumnerror(VS.80).aspx

     

    にエラー文字列をセットすれば検証が失敗しデータセットへの更新はなされなくなるかな、と期待したのですが、何のメッセージも出ず値はデータセットに更新されました。以下がそのコードです。

     

    Code Snippet
    Partial Class DataSet1
        Partial Class DataTable1DataTable
            Private Sub DataTable1DataTable_ColumnChanging(ByVal sender As System.Object, ByVal e As System.Data.DataColumnChangeEventArgs) Handles Me.ColumnChanging
                If (e.Column.ColumnName = Me.Column1Column.ColumnName) Then
                    'ユーザー コードをここに追加してください
                    If Len(CStr(e.ProposedValue)) > 2 Then
                        e.Row.SetColumnError(e.Column, "形式エラー")
                        Console.WriteLine("ここ通った。")
                    Else
                        e.Row.SetColumnError(e.Column, "")
                    End If
                End If
            End Sub
        End Class
    End Class

     

     

    検証って一体何を指しているのでしょう?

    2007年9月8日 11:23
  • 質問の答えになってないかもしれませんが、(^^;

    DataTableは更新されてませんよ。

    CancelEditかけるとキャンセルできます。

    他レコードに移るとDataTableが更新されますが、

    e.Cancel=Trueをしてると、他レコードに移る手段がありません。

     

    2007年9月9日 13:00