データグリッドビュー DataGridView コントロールを操作する 101 の方法 初めに Windows Forms プログラミングで普段良く使われるコントロールの一つに DataGridView が有る DataGridView は Windows Forms 2.0 で新たに登場したコントロールで Windows Forms 1.0 の DataGrid コントロールの後継と成る物で有る 非常に強力で用途の広いコントロールで有り 各種のデータソースを表形式で表示するのに向いて居る 柔軟性が高い故に 公開されて居るプロパティ メソッド イベントも多数に上り 初心者には可成り取っ付き難いコントロールと謂える 本稿は プログラミングの現場で DataGridView コントロールを直ぐ使い熟せる様にする事を目指して居る 一般的なタスクを粗カバーするよう努めたが DataGridView コントロールの全機能を網羅して居る訳では無い 本稿では Windows アプリケーションプロジェクトのデフォルトのフォーム Form1 に DataGridView コントロールを配置する物と仮定する ( 図 1) 図 1: 手始めに新規の Windows アプリケーションプロジェクトを作成し Form1 に DataGridView コントロールを配置する 配列をバインドする DataGridView コントロールに配列をバインドする事が出来る 次の例を観て欲しい Dim arr( ) As String = {"Product 1", "Product 24", "Product 356"} DataGridView1.DataSource = arr arr( ) は 3 個の要素を持つ文字列配列で有る DataSource プロパティを用いて DataGridView コントロールにバインドされて居る 図 2 に 此のデータバインドの結果を示す -1-
図 2: 文字列配列を DataGridView コントロールにバインドした結果 此の結果は意外な物かも知れない 恐らく 配列の各要素が表示されると予想して居たと思う 実際には 各要素の長さが表示される DataGridView コントロールはバインドされたオブジェクトの最初のパブリックプロパティを探すからで有る 此の例では 文字列配列の最初のパブリックプロパティは配列内の各要素の長さなので 上の様な結果が得られる訳で有る 文字列配列を DataGridView コントロールに正しくバインドする為には 次に示す様に文字列型をラップするクラスを作成し 此のクラスが 要素の内容を返すパブリックプロパティ Name を公開する様にする Public Class CStringItem Private _str As String Public Sub New(ByVal str As String) _str = str Public Property Name( ) As String Get Return _str End Get Set(ByVal value As String) _str = value End Set End Property End Class 次の例では arr( ) を CStringItem 型の配列として宣言し 3 個の要素を初期設定した後で DataGridView コントロールにバインドする Dim arr( ) As CStringItem = { _ New CStringItem("Product 1"), _ New CStringItem("Product 2"), _ New CStringItem("Product 3")} DataGridView1.DataSource = arr 図 3 は 此のデータバインドの結果で有る パブリックプロパティ Name が DataGridView コントロール内の列の見出しテキストと仕て使われて居る事に注意して欲しい 図 3:DataGridView コントロールにオブジェクトの配列をバインドした結果 -2-
カスタムオブジェクトをバインドする 次の例では DataGridView コントロールに更に複雑なオブジェクトをバインドする方法を説明する 2 つのパブリックプロパティ (Name ID) を持つ CStudent クラスを定義する Public Class CStudent Private _name As String Private _ID As String Public Sub New(ByVal id As String, ByVal name As String) _ID = id _name = name Public Property Name( ) As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Public Property ID( ) As String Get Return _ID End Get Set(ByVal value As String) _ID = value End Set End Property End Class DataGridView コントロールに CStudent オブジェクトの配列をバインドすると 図 4 の結果が得られる Dim students() As CStudent = _ {New CStudent("123-456-789", "John"), New CStudent("456-123-789", "Mary")} DataGridView1.DataSource = students 図 4:DataGridView コントロールに CStudent オブジェクトの配列をバインドした結果 型指定されたデータセットを用いてバインドする DataGridView コントロールが特に良く使われるのは データベースのテーブルをバインドするケースで有る 此れを説明する為に 現在のプロジェクトに型指定されたデータセットを追加する Visual Studio 2005 のソリューションエクスプローラでプロジェクト名を右クリックし [ 追加 ] [ 新しい項目の追加 ] を選択する データセットテンプレートを選択し (DataSet1.xsd のデフォルトの名前を使用 ) [ 追加 ] をクリックする -3-
サーバエクスプローラを起動し ([ 表示 ] [ サーバエクスプローラ ]) Northwind サンプルデータベースに移動する (SQL Server/SQL Server Express でインストールされて居る物と仮定 ) Customers テーブルを DataSet1.xsd のデザインサーフェイスにドラッグ & ドロップする 図 5 は 型指定されたデータセットを作成する様子を示して居る 図 5: 型指定されたデータセットを作成する 次のステップには 2 つの選択肢が有る 1 つは 次に示す様に DataGridView コントロールに Customers テーブルのテーブルアダプタを直接バインドする方法で有る ' テーブルアダプターのインスタンスを生成 Dim adapter As New CustomersTableAdapter ' データグリッドビューにバインド DataGridView1.DataSource = adapter.getdata 今 1 つは BindingSource コントロールを使用する方法で有る ' テーブルアダプターのインスタンスを生成 Dim adapter As New CustomersTableAdapter ' バインディングソースのインスタンスを生成 Dim bindingsrc As New BindingSource ' バインディングソースのデータソースを設定 bindingsrc.datasource = adapter.getdata ' データグリッドビューにバインド DataGridView1.DataSource = bindingsrc 猶 上のコードが正常に実行される様にする為には 次の様に名前空間をインポートして置く必要が有る (DVG は 此のプロジェクトの名前で有る ) -4-
Imports DGV.DataSet1TableAdapters 図 6 は 此のデータバインドの結果で有る 図 6: 型指定されたデータセットをバインドした結果 データセットでバインドする データセットを手動で作成する場合は DataSource プロパティにデータセットを設定し 表示するテーブルを DataMember プロパティに指定すれば DataGridView コントロールにバインド出来る 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( ) ' 接続をオープン conn.open( ) ' データセットのフィル dataadapter.fill(ds, "Customers_table") ' 接続のクローズ conn.close( ) ' データグリッドビューにバインド DataGridView1.DataSource = ds ' データセットのテーブルを設定 DataGridView1.DataMember = "Customers_table" クリックされたセルを検出する ユーザーのクリックした DataGridView コントロール内のセルの値を取得する場合は CellEnter イベントを処理する -5-
' データグリッドビューをクリックした時の処理 Private Sub DataGridView1_CellEnter( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _ Handles DataGridView1.CellEnter ' セルの内容を出力 Console.WriteLine( DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) RowIndex プロパティと ColumnIndex プロパティに 現在選択されて居るセルの行番号と列番号が夫々れ設定される DataView でフィルタリングする DataGridView コントロールに表示されるデータにフィルタを懸けるには DataView オブジェクトを使用する ' テーブルアダプターのインスタンスの生成 Dim adapter As New CustomersTableAdapter ' データビューのインスタンスの生成 Dim dv As New DataView(adapter.GetData) With dv.allownew = False.AllowDelete = True.Sort = "ContactTitle ASC, Address ASC".RowFilter = "CustomerID LIKE 'B*'" End With ' データグリッドビューにバインド DataGridView1.DataSource = dv 上の例は DataView オブジェクトを使う事に依り DataGridView コントロールにユーザーが新しい行を追加するのを許可したり (AllowNew プロパティ ) 行を削除するのを許可したり (AllowDelete プロパティ ) 出来る事を示して居る 亦 フィールドとソート順序を指定して行をソートする事も出来る (Sort プロパティ ) 更に SQL に似た式を指定してレコードにフィルタを懸ける事も出来る (RowFilter プロパティ ) 上の例では CustomerID フィールドが B で始まるレコード丈を抽出する様に レコードにフィルタを懸けて居る 亦 行を ContactTitle フィールドの昇順でソートし 更に Address フィールドの昇順でソートして居る Address フィールドの降順でソートする場合は 次の様に設定する.Sort = "ContactTitle ASC, Address DESC" 図 7 に ContactTitle フィールドと Address フィールドを共に昇順でソートしたケースと ContactTitle を昇順 Address を降順でソートしたケースを示す -6-
図 7:ContactTitle と Address のソート順序に依る違い 列をソートする DataView オブジェクトを使えばフィルタリングやソートを実行出来るが DataGridView コントロールの Sort( ) メソッドでもソートを制御出来る ' 最初の列 ( フィールド ) でソート DataGridView1.Sort(DataGridView1.Columns(0), _ System.ComponentModel.ListSortDirection.Descending) 此の例では 行を最初の列の降順でソートして居る ( 図 8) 図 8: 最初の列を降順でソートする -7-
プログラムに依るソートとは別に ユーザーが実行時にソートグリフ ( 列見出しの隣に表示される三角形のアイコン ) をクリックして行を昇順または降順にソートする事も可能で有る 行がソートされない様にするには SortMode プロパティを NotSortable に設定する ' 列 ( フィールド ) のソートモードの設定 DataGridView1.Columns(1).SortMode = _ DataGridViewColumnSortMode.NotSortable プログラミングに依り列を追加する 此れ迄に紹介した方法は データセットや BindingSource コントロールを用いて DataGridView コントロールにデータベースをバインドすると謂う物だった 併し 時にはプログラミングに依り DataGridView コントロール内に様々なフィールドを作成し ユーザーに値を設定させる場合も有る ( 同様に プログラミングに依り新しい行を追加する事も出来る ) DataGridView コントロール内に列を作成するには DataGridView コントロールの Columns プロパティの Add( ) メソッドを使用する 次の例では DataGridView コントロール内に 4 つのフィールドを作成して居る ' 列 ( フィールド ) の追加 DataGridView1.Columns.Add("ID", "Product ID") DataGridView1.Columns.Add("Name", "Product Name") DataGridView1.Columns.Add("Description", "Description") DataGridView1.Columns.Add("Price", "Price") 図 9 は 此の DataGridView コントロールの表示結果で有る 図 9:DataGridView コントロールに 4 つのフィールドを作成する 行を追加する DataGridView コントロールに行を追加するには Rows プロパティの Add( ) メソッドを使用する ' 空の行 ( レコード ) の追加 DataGridView1.Rows.Add( ) 行を追加して 其処に内容を割り当てるには DataGridViewRow クラスのインスタンスを作成してから CreateCells( ) メソッドで行テンプレートを作成する For i As Integer = 0 To 9 ' 行 ( レコード ) の作成 Dim item As New DataGridViewRow item.createcells(datagridview1) With item.cells(0).value = i.cells(1).value = "Product " & i.cells(2).value = "Description of Product " & i.cells(3).value = "99.99" End With ' 行 ( レコード ) の追加 DataGridView1.Rows.Add(item) Next -8-
行の各フィールドに割り当てる一連の値を配列に格納し 其の配列を使用して新しい行を追加する事も出来る For i As Integer = 0 To 9 DataGridView1.Rows.Add(New String( ) _ {i, "Product " & i, "Description of Product " & i, "99.99"}) Next 図 10 は 上の 2 つの例の出力で有る 図 10: プログラミングに依り DataGridView コントロールに新しい行を追加する セルにコンボボックスを表示する セルにテキストを表示する丈でなく ドロップダウンリストボックスを表示して 予め決められた値をリストから選択出来る様に仕度い事が有る 其の場合は 目的の列のセルにコンボボックスを追加する必要が有る 次の例では DataGridView コントロールの 5 番目の列に ComboBox コントロールを追加して居る ' データグリッドビューに列の追加 DataGridView1.Columns.Add("ID", "Product ID") DataGridView1.Columns.Add("Name", "Product Name") DataGridView1.Columns.Add("Description", "Description") DataGridView1.Columns.Add("Price", "Price") ' バインディングソースの生成 Dim bindingsource As New BindingSource ' バインディングソースにアイテムの追加 bindingsource.add("type A") bindingsource.add("type B") bindingsource.add("type C") ' コンボボックスの列の生成 Dim comboboxcol As New DataGridViewComboBoxColumn ' ヘッダの設定 comboboxcol.headertext = "Types" ' データのバインド comboboxcol.datasource = bindingsource ' コンボボックス列をデータグリッドビューに追加 DataGridView1.Columns.Add(comboBoxCol) -9-
此の出力結果を図 11 に示す 図 11:DataGridView のセルに ComboBox を追加する 上の例では 項目リストを含んだ BindingSource コントロールを DataGridView コントロール内の DataGridViewComboBoxColumn コントロールにバインドする方法を示したが DataGridViewComboBoxColumn コントロールに項目を直接追加する方法も有る ' データグリッドビューに列の追加 DataGridView1.Columns.Add("ID", "Product ID") DataGridView1.Columns.Add("Name", "Product Name") DataGridView1.Columns.Add("Description", "Description") DataGridView1.Columns.Add("Price", "Price") ' コンボボックスの列の生成 Dim comboboxcol As New DataGridViewComboBoxColumn ' ヘッダの設定 comboboxcol.headertext = "Types" ' コンボボックスにアイテムの追加 comboboxcol.items.add("type A") comboboxcol.items.add("type B") comboboxcol.items.add("type C") ' コンボボックス列をデータグリッドビューに追加 DataGridView1.Columns.Add(comboBoxCol) 後者の方がより柔軟で有り 此の方法で実装して居ると 実行時にユーザーがドロップダウンリストに新しい項目を追加出来る ( 詳細に付いては次のセクションを参照 ) ComboBox コントロールにデータソースをバインドすると 新しい項目を実行時に追加出来なく成る DataGridViewComboBoxColumn コントロールに項目を追加する 前のセクションでは DataGridView コントロール内のセルに ComboBox コントロールを表示する方法を示した ComboBox コントロールにユーザーが新しい項目を挿入出来る様に仕度い事が有る 其の為には 少し準備が必要で有る 先ず DataGridView コントロールの EditingControlShowing イベントを処理する 此のイベントは ユーザーが ComboBox コントロールを編集しようとした時に発生する Private Sub DataGridView1_EditingControlShowing( ByVal sender As Object, _ ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _ Handles DataGridView1.EditingControlShowing Dim comboboxcolumn As DataGridViewComboBoxColumn = DataGridView1.Columns(4) If (DataGridView1.CurrentCellAddress.X = comboboxcolumn.displayindex) Then Dim cb As ComboBox = e.control If (cb IsNot Nothing) Then cb.dropdownstyle = ComboBoxStyle.DropDown -10-
此処でのポイントは 編集対象のセルが ComboBox を含むセルか何うかを確認する事で有る ComboBox を含んで居る場合は ComboBox コントロールのドロップダウンスタイルを DropDown に設定して ユーザーに依る追加入力が出来る様にする 次に DataGridView コントロールの CellValidating イベントを処理する 此のイベントはユーザーが入力を終了してセルを離れた時に発生する Private Sub DataGridView1_CellValidating( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ DataGridViewCellValidatingEventArgs) _ Handles DataGridView1.CellValidating Dim comboboxcolumn As DataGridViewComboBoxColumn = DataGridView1.Columns(4) If (e.columnindex = comboboxcolumn.displayindex) Then If (Not comboboxcolumn.items.contains( e.formattedvalue)) Then comboboxcolumn.items.add(e.formattedvalue) 此処では 通常のチェックを行った後に 新しく入力された項目を ComboBox に追加する 図 12 を観ると ComboBox には最初 3 個の項目が有る 此処にユーザーが新しい項目 ( 例えば Type D) を入力出来 其れがリストに追加される 実際に操作した行より前 又は 後ろの行でも ComboBox コントロールの項目数が 4 に成る事に注意して欲しい 図 12: ユーザーが新しい項目を ComboBox コントロールに追加出来る 行 / 列をロックする 行の ReadOnly プロパティを True に設定すると 特定の行が変更されない様にロック出来る ' 最初の行 ( レコード ) を読取専用に設定 DataGridView1.Rows(0).ReadOnly = True 同様に 特定の列に属するセルをロックする事も出来る ' 最初の列 ( フィールド ) を読取専用に設定 DataGridView1.Columns(0).ReadOnly = True ReadOnly プロパティを True に設定するとセルの値は変更されなく成るが 行の削除が出来なく成る訳では無い 必要なら DataGridView コントロール全体をロックする事も出来る ' データグリッドビュー全体を読取専用に設定 DataGridView1.ReadOnly = True -11-
列を非表示にする 実行時に列の Visible プロパティを False に設定する事で 特定の列を非表示に出来る ' 2 番目の列 ( フィールド ) を非表示に設定 DataGridView1.Columns(1).Visible = False 図 13 に 列を非表示にした DataGridView の例を示す 奥は総ての列を表示した状態で 手前は 2 番目の列 (CompanyName 列 ) を非表示にした状態で有る 図 13: 列を非表示にする前と後の DataGridView ユーザーの編集を検証する DataGridView コントロールの一般的な用途の 1 つはデータ入力で有る ユーザーはコントロールの個々のセルにデータを入力する 其の為 正しい種類のデータが入力されたか何うかを検証する事が重要で有る 入力されたデータの種類が正しい事を検証するには 2 つのイベントを処理する必要が有る 最初に CellValidating イベントを処理する 此のイベントは ユーザーがセルの値を変更してセルを離れた時に発生する Private Sub DataGridView1_CellValidating( ByVal sender As Object, _ ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) _ Handles DataGridView1.CellValidating 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 -12-
此のイベント内で必要な検証を行う 例えば上の例では 4 番目の列 ( 列インデックスの Price フィールド ) に数値以外が含まれて居ない事を確認する 数値以外が含まれて居る場合は DataGridView コントロールの一番左の列にエラーメッセージを表示する (ErrorText プロパティ ) 図 14 に例を示す 図 14: 此の画面のコントロールは セルの値を検証し 左側の列にエラーメッセージを表示する ユーザーはエラーを訂正しないと他のセルに移動出来ない 訂正データが入力された時にエラーメッセージが消える様にするには CellEndEdit イベントを処理する Private Sub DataGridView1_CellEndEdit( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _ Handles DataGridView1.CellEndEdit ' エラーメッセージの消去 DataGridView1.Rows(e.RowIndex).ErrorText = String.Empty 入力を制限する 前のセクションでは ユーザーの入力したセルの値を検証する方法を示した 併し 状況に依っては 此れでも未だ充分で無い 最初から不正な文字が入力されない様にした方が良い事も有る 此れは 前のセクションの例で考えると Price フィールドに数字以外の文字が入力されない様にする事を意味する 普通の TextBox コントロールでは 此の問題は KeyPress イベントを処理する事で解決出来る 併し 此の方法を DataGridView コントロールに適用する為には少し準備が必要で有る 先ず EditingControlShowing イベントを処理する 此のイベントはユーザーがセルの内容を編集しようとした時に発生する Private Sub DataGridView1_EditingControlShowing( _ ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ DataGridViewEditingControlShowingEventArgs) _ Handles DataGridView1.EditingControlShowing ' 4 番目のフィールドの入力制限 If Me.DataGridView1.CurrentCell.ColumnIndex = 3 And _ Not e.control Is Nothing Then Dim tb As TextBox = CType(e.Control, TextBox) ' テキストボックスへのイベントハンドラの追加 AddHandler tb.keypress, AddressOf TextBox_KeyPress 此処では 制限し度い TextBox コントロールに KeyPress イベントハンドラを追加する 此の KeyPress イベントハンドラは ユーザーがセルに入力を行った時に呼び出される 此の定義は次の通りで有る -13-
Private Sub TextBox_KeyPress( ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) ' テキストボックスが空で小数点キーを押した場合 If CType(sender, TextBox).Text = String.Empty And e.keychar = Chr(46) Then e.handled = True Return ' 既に小数点が存在する場合 If CType(sender, TextBox).Text.Contains(Chr(46)) And e.keychar = Chr(46) Then e.handled = True Return ' 数値以外のキーが押された場合 If (Not (Char.IsDigit(e.KeyChar) Or _ Char.IsControl(e.KeyChar) Or _ (e.keychar = Chr(46)))) Then e.handled = True 上記のコードは ユーザーの入力を数字 ( 小数点. を含む ) に而巳制限する 其れ以外の文字が入力されてもセルには現れない 行を削除する プログラミングに依り 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 -14-
此のコードに依り 行の削除を実行して良いかを確認するプロンプトが表示される ( 図 15) 図 15:UserDeletingRow イベントでユーザーに確認を求めてから実際の削除を行う 変更を保存する 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() ' 接続を開きデータセットをフィル 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 オブジェクトにデータベース内のテーブルを更新させる -15-
型指定されたデータセットが 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 を使用してデータベースや其の他のデータソースを表示しようと考えて居るプログラマのリファレンスとして役立てば幸いで有る -16-