ユーザーの編集を検証する
DataGridViewコントロールの一般的な用途の1つはデータ入力です。ユーザーはコントロールの個々のセルにデータを入力します。そのため、正しい種類のデータが入力されたかどうかを検証することが重要です。
入力されたデータの種類が正しいことを検証するには、2つのイベントを処理する必要があります。最初にCellValidatingイベントを処理します。このイベントは、ユーザーがセルの値を変更してセルを離れたときに発生します。
Private Sub DataGridView1_CellValidating( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ DataGridViewCellValidatingEventArgs) _ Handles DataGridView1.CellValidating '---Price field--- If e.ColumnIndex = 3 Then If Not IsNumeric(e.FormattedValue) Then DataGridView1.Rows(e.RowIndex).ErrorText = _ "Price must be a numeric value." e.Cancel = True End If End If End Sub
このイベント内で必要な検証を行います。例えば上の例では、4番目の列(列インデックスのPriceフィールド)に数値以外が含まれていないことを確認します。数値以外が含まれている場合は、DataGridViewコントロールの一番左の列にエラーメッセージを表示します(ErrorTextプロパティ)。図14に例を示します。
ユーザーはエラーを訂正しないと他のセルに移動できません。訂正データが入力されたときにエラーメッセージが消えるようにするには、CellEndEditイベントを処理します。
Private Sub DataGridView1_CellEndEdit( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _ Handles DataGridView1.CellEndEdit '---clear the error message--- DataGridView1.Rows(e.RowIndex).ErrorText = String.Empty End Sub
入力を制限する
前のセクションでは、ユーザーの入力したセルの値を検証する方法を示しました。しかし、状況によっては、これでもまだ十分でありません。最初から不正な文字が入力されないようにした方が良いこともあります。これは、前のセクションの例で考えると、Priceフィールドに数字以外の文字が入力されないようにすることを意味します。普通のTextBoxコントロールでは、この問題はKeyPressイベントを処理することで解決できます。しかし、この方法をDataGridViewコントロールに適用するためには少し準備が必要です。
まず、EditingControlShowingイベントを処理します。このイベントはユーザーがセルの内容を編集しようとしたときに発生します。
Private Sub DataGridView1_EditingControlShowing( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ DataGridViewEditingControlShowingEventArgs) _ Handles DataGridView1.EditingControlShowing '---restrict inputs on the fourth field--- If Me.DataGridView1.CurrentCell.ColumnIndex = 3 And _ Not e.Control Is Nothing Then Dim tb As TextBox = CType(e.Control, TextBox) '---add an event handler to the TextBox control--- AddHandler tb.KeyPress, AddressOf TextBox_KeyPress End If End Sub
ここでは、制限したいTextBoxコントロールにKeyPressイベントハンドラを追加します。このKeyPressイベントハンドラは、ユーザーがセルに入力を行ったときに呼び出されます。この定義は次のとおりです。
Private Sub TextBox_KeyPress( _ ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) '---if textbox is empty and user pressed a decimal char--- If CType(sender, TextBox).Text = String.Empty And _ e.KeyChar = Chr(46) Then e.Handled = True Return End If '---if textbox already has a decimal point--- If CType(sender, TextBox).Text.Contains(Chr(46)) And _ e.KeyChar = Chr(46) Then e.Handled = True Return End If '---if the key pressed is not a valid decimal number--- If (Not (Char.IsDigit(e.KeyChar) Or _ Char.IsControl(e.KeyChar) Or _ (e.KeyChar = Chr(46)))) Then e.Handled = True End If End Sub
上記のコードは、ユーザーの入力を数字(「.」も含む)にのみ制限します。それ以外の文字が入力されてもセルには現れません。
行を削除する
プログラミングによってDataGridViewコントロール内の行を削除するには、Remove()メソッドを使います。次のコードはDataGridViewコントロール内の選択された行をすべて削除します。
For Each row As DataGridViewRow In DataGridView1.SelectedRows DataGridView1.Rows.Remove(row) Next
ユーザーは最初に行を選択して[Delete]キーを押す方法でも行を削除できます。デフォルトで、この削除は確認なしに自動で実行されます。しかし、削除の前にユーザーに確認を求めることもできます。これにはUserDeletingRowイベントを使います。
Private Sub DataGridView1_UserDeletingRow( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ DataGridViewRowCancelEventArgs) _ Handles DataGridView1.UserDeletingRow If (Not e.Row.IsNewRow) Then Dim response As DialogResult = _ MessageBox.Show( _ "Are you sure you want to delete this row?", _ "Delete row?", _ MessageBoxButtons.YesNo, _ MessageBoxIcon.Question, _ MessageBoxDefaultButton.Button2) If (response = DialogResult.No) Then e.Cancel = True End If End If End Sub
このコードにより、行の削除を実行してよいかを確認するプロンプトが表示されます(図15)。
変更を保存する
DataGridViewコントロールにデータベースのデータソースをバインドした場合、DataGridViewコントロールにおけるすべての変更がデータベースに自動的に反映されるわけではありません。そのため、すべての変更を手動でデータベースに戻す必要があります。
以前紹介した、DataGridViewコントロールにデータセットをバインドする例をもう一度考えます。次のコードは、データセットに「Customers」テーブルを読み込みます。
Dim connStr As String = _ "Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;" & _ "Integrated Security=True" Dim sql As String = "SELECT * FROM Customers" Dim conn As SqlConnection = New SqlConnection(connStr) Dim comm As SqlCommand = New SqlCommand(Sql, conn) Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm) Dim ds As DataSet = New DataSet() '---open the connection and fill the dataset--- conn.Open() dataadapter.Fill(ds, "Customers_table") conn.Close() DataGridView1.DataSource = ds DataGridView1.DataMember = "Customers_table"
DataGridViewコントロールでの変更をデータベースに戻すには、次のようにします。
Dim sqlCmdBuilder As New SqlCommandBuilder(dataadapter) sqlCmdBuilder.GetUpdateCommand() dataadapter.Update(ds.Tables("Customers_table"))
SqlCommandBuilderオブジェクトのGetUpdateCommand()メソッドによって、DataGridViewコントロールの変更を反映するSQLステートメントを自動的に作成します。その後、SqlDataAdapterオブジェクトにデータベース内のテーブルを更新させます。
型指定されたデータセットがDataGridViewコントロールに以下のような方法でバインドされている場合、
Dim adapter As New CustomersTableAdapter Dim bindingSrc As New BindingSource bindingSrc.DataSource = adapter.GetData DataGridView1.DataSource = bindingSrc
次のコードで変更をデータベースに簡単に反映させることができます。
bindingSrc.EndEdit() adapter.Update(bindingSrc.DataSource)
変更が文字列などに保存されている場合は、DataGridViewコントロール内のすべての行と列をループで処理します。
Dim output As String = String.Empty For Each row As DataGridViewRow In DataGridView1.Rows For Each cell As DataGridViewCell In row.Cells output += cell.Value & ":" Next output += vbCrLf Next MsgBox(output)
おわりに
本稿では、DataGridViewコントロール関連の一般的なタスクをどのように実行すればよいかを考察しました。DataGridViewは非常に用途の広いコントロールです。本稿が、DataGridViewを使用してデータベースやその他のデータソースを表示しようと考えているプログラマのリファレンスとして役立てば幸いです。


