lazy-programmer
24-01-2003, 15:33
Sử Dụng DataGrid.Net Phần II
Note: Bạn có thể download bài viết dạng .doc và sourcecode gởi kèm
3. Nắm Toàn Quyền Điều Khiển Giao Diện DataGrid.Net
Cho đến giờ, bạn đã có một Datagrid có Combobox ở cột SupplierID nhưng bạn không thể hiển thị tên của các Suppliers thay vì các ID, ngoài ra cấu trúc của các cột phụ thuộc vào cấu trúc của dataset. Bạn sẽ phải làm gì nếu muốn thay đổi thứ tự các cột (VD: đưa cột “Discontinued” lên đầu tiên?)
Bạn hãy xem giao diện được cải thiện như dưới đây:
(To see picture, download attached file)
So với phiên bản trước, phiên bản này có những cải tiến sau:
Các cột có thể di chuyển tới vị trí bất kỳ, không phụ thuộc vào cấu trúc của datasource (datatable) nữa. VD: Cột “Discontinued” được di chuyển lên vị trí đầu tiên.
Các header cột thể hiện tên tùy ý. VD: “Unit Price” thay vì “UnitPrice”.
Cột “Supplier” với tên đầy đủ của các nhà cung cấp thay cho cột “SupplierID” với những mã số kém trực quan.
Để thực hiện được việc này, trước hết chúng ta hãy xem qua một vài kỹ thuật có thể áp dụng được trong Datagrid.Net:
Datagrid.Net có hai dạng cột (column styles) có sẵn là Textbox (DataGridTextBoxColumn) và Checkbox (DataGridBoolColumn), bạn có thể tạo/thêm các cột này vào lúc thiết kế hay runtime. Nếu không, khi bạn gắn Datagrid vào CSDL, nó sẽ tự tạo ra các cột tương ứng với các cột dữ liệu theo cấu trúc của Dataset, nếu các cột có dữ liệu dạng False/True thì sẽ được hiển thị trong DataGridBoolColumn còn các dạng khác sẽ bị biến thành dạng text hết và hiển thị trong DataGridTextBoxColumn. Ngoài ra, bạn có thể tự tạo ra các column style khác (custom) và gắn vào datagrid (tôi sẽ đề cập tới vấn đề này trong một bài khác).
Các cột của Datagrid.Net có thể gắn kết với một cột dữ liệu (bound) hay hoàn toàn độc lập với CSDL. Để gắn chính xác một cột của Datagrid.Net với một cột trong datatable, ta sẽ sử dụng kỹ thuật Mapping Name - nghĩa là gán tên cột dữ liệu vào cột của Datagrid.
Ngoài ra ta cũng có thể thêm các cột dữ liệu unbound vào Datatable, các cột này sẽ không dùng để update CSDL chính mà chỉ dùng để thể hiện các dữ liệu theo ý của bạn.
Hình thức thể hiện (màu sắc, font chữ...) của Datagrid.Net có thể thay đổi thông qua các DataGridTableStyle gắn kết với nó. Xin các bạn xem lại đoạn code tạo và sử dụng TableStyle trong Phần I (ở thủ tục PopulateGrid()):
[/list=1]
If (Not dgdProducts.TableStyles.Contains("Products")) Then
'Create a DataGridTableStyle object
Dim dgdtblStyle As New DataGridTableStyle()
'Set its properties
dgdtblStyle.MappingName = tblProducts.TableName 'its table name of dataset
dgdProducts.TableStyles.Add(dgdtblStyle)
dgdtblStyle.AlternatingBackColor = Color.Yellow
dgdtblStyle.AllowSorting = True
dgdtblStyle.RowHeadersVisible =
dgdtblStyle.HeaderFont = New System.Drawing.Font("Microsoft Sans Serif", 9.0F, System.Drawing.FontStyle.Bold, GraphicsUnit.Point, 0)
dgdtblStyle.GridLineColor = Color.DarkGray
dgdtblStyle.PreferredRowHeight = 22
dgdProducts.BackgroundColor = Color.White
End If
Bây giờ chúng ta hãy bắt tay vào tạo dựng Datagrid của mình.
Bước 1: Thêm cột unbound “Supplier” vào datatable tblProducts
Trong thủ tục PopulateGrid(), sau phần tạo Combobox bạn thêm đoạn mã sau:
'Add an unbound column that comtain Combobox to main datatable
Dim dcolCombo As DataColumn
dcolCombo = New DataColumn("Supplier")
With dcolCombo
.DataType = System.Type.GetType("System.String")
.DefaultValue = ""
End With
tblProducts.Columns.Add(dcolCombo)
Lúc này cột dữ liệu mới thêm vào hoàn toàn trống rổng, bạn phải fill dữ liệu – tên các supplier – vào bằng cách gọi thủ tục:
FillUnboundColumn()
và viết code để fill tên Supplier tương ứng với SupplierID trong bảng “Products”. Hai thủ tục/hàm sau sẽ giúp bạn thực hiiện điều này:
Private Sub FillUnboundColumn()
Dim i As Integer
Dim dRow As DataRow
'Go to each row of unbound column "Supplier" and fill with meaningful data
For i = 0 To tblProducts.Rows.Count - 1
dRow = tblProducts.Rows(i)
'Fill "Supplier" column with supplier name inaccordance with SupplierID
dRow("Supplier") = FindSupplierName(dRow("SupplierID"))
Next
'Set default value for "SupplierID" column, so that when you add new row
'the Datagrid will behave correctly
tblProducts.Columns("SupplierID").DefaultValue = 1
End Sub
Private Function FindSupplierName(ByVal ID As Integer) As String
Dim i As Integer
Dim dRow As DataRow
For i = 0 To tblSuppliers.Rows.Count - 1
dRow = tblSuppliers.Rows(i)
If dRow(0) = ID Then
Return dRow(1).ToString
End If
Next
End Function
Bước 2: Tạo mới các column trong Datagrid
Như vậy hiện giờ tblProducts có 7 cột dữ liệu, để thể hiện chúng theo ý mình, bạn cần tạo ra 7 cột tương ứng trong Datagrid. Nếu bạn muốn cột đó có chứa CheckBox thì bạn tạo loại cột DataGridBoolColumn, còn không bạn tạo dạng DataGridTextBoxColumn. Ở đây ta muốn đưa cột “Discontinued” là dạng False/True lên đầu tiên để tiện theo dõi những hàng nào không còn đặt mua nữa. Ta thêm đoạn code sau vào ngay sau phần tạo và format DataGridTableStyle vừa trình bày ở trên:
Private Sub PopulateGrid()
…
If (Not dgdProducts.TableStyles.Contains("Products")) Then
…
Dim i As Integer
For i = 0 To 6
If i <> 0 Then
Dim gridcol As New DataGridTextBoxColumn()
dgdtblStyle.GridColumnStyles.Add(gridcol)
Else
Dim gridcol As New DataGridBoolColumn()
dgdtblStyle.GridColumnStyles.Add(gridcol)
End If
Next
End If
End Sub
Bước 3: Gán các cột trong datatable tblProducts vào các cột của Datagrid.Net
Sau khi tạo ra các cột, việc tiếp theo là chúng ta phải làm cho Datagrid hiểu cột nào sẽ thể hiện dữ liệu của cột nào trong datatable và định ra header text, chiều rộng của các cột. Thêm vào phần code như dưới đây:
Private Sub PopulateGrid()
...
If (Not dgdProducts.TableStyles.Contains("Products")) Then
...
...
'Mapping datagrid columns to column names of “tblProducts” and
'format header text and column width.
Dim colStyle As GridColumnStylesCollection
colStyle = dgdProducts.TableStyles(0).GridColumnStyles
colStyle(0).MappingName = "Discontinued"
colStyle(0).HeaderText = "Discontinued"
'
colStyle(1).MappingName = "ProductID"
colStyle(1).HeaderText = "Product ID"
'
colStyle(2).MappingName = "ProductName"
colStyle(2).HeaderText = "Product Name"
colStyle(2).Width = 150
'
colStyle(3).MappingName = "Supplier"
colStyle(3).HeaderText = "Supplier"
colStyle(3).Width = "150"
'
colStyle(4).MappingName = "QuantityPerUnit"
colStyle(4).HeaderText = "Quantity"
'
colStyle(5).MappingName = "UnitPrice"
colStyle(5).HeaderText = "Unit Price"
'
colStyle(6).MappingName = "SupplierID"
colStyle(6).Width = 0
End If
'To add the combo box dynamically to the data grid, you have to take the
'Text Box that is present (by default) in the column where u want to add
'this combo box (here it is third column i.e. Supplier).From the
'tablestyles of the data grid take the grid column styles of the column
'where you want to add the combo box respectively.
Dim dgtb As DataGridTextBoxColumn = dgdProducts.TableStyles(0).GridColumnStyles(3)
'Add the combo box to the text box taken in the above step
dgtb.TextBox.Controls.Add(cboSupplier)
'Set DataGrid source as the table "Products"
dgdProducts.DataSource = tblProducts
End Sub
=>Ở đây bạn lưu ý hai điểm sau:
[list]
Cột SupplierID được đưa ra sau cùng và có chiều rộng là 0, nghĩa là người sử dụng sẽ không thấy được cột này.
Bạn phải đặt DataSource cho datagrid sau khi đã mapping name nếu không khi chạy chương trình sẽ báo lỗi là không thể Mapping name được vì tên này đã có rồi.
Bước 4: Bỏ qua hoàn toàn cột SupplierID
Mặc dù ở bước trên, bạn đã cho cột SupplierID ẩn dấu nhưng nó chưa thực sự “biến mất” hoàn toàn. Nếu bạn dùng tab di chuyển giữa các ô của Datagrid bạn sẽ nhận thấy nó vẫn dừng lại ở cột cuối cùng dù không nhìn thấy. Để bỏ qua cột này, chúng ta phải thêm một thủ tục để khi một cell trong cột này nhận focus nó sẽ chuyển ngay focus về cell của cột đầu tiên, hàng tiếp theo.
Muốn vậy, bạn thêm một handler điều khiển việc nhận focus của textbox trong cột SupplierID (cột 6). Gõ vào đoạn mã này vào cuối thủ tục PopulateGrid():
'Add handlers to control grid navigation so that all hided columns will be passed by
dgtb = dgdProducts.TableStyles(0).GridColumnStyles(6)
AddHandler dgtb.TextBox.GotFocus, AddressOf Col6_GotFocus
Và viết thủ tục Col6_GotFocus:
Private Sub Col6_GotFocus(ByVal sender As Object, ByVal e As EventArgs)
Dim colnum As Integer = dgdProducts.CurrentCell.ColumnNumber
If colnum <> 6 Then Exit Sub
'Set focus to the cell of first column, next row
Dim cell As New DataGridCell(dgdProducts.CurrentRowIndex + 1, 0)
dgdProducts.CurrentCell = cell
End Sub
Bước 5: Làm cho ComboBox cập nhật đúng dữ liệu
Khi bạn chọn một item mới trong ComboBox ở cột “Supplier”, ComboBox sẽ phải cập nhật phần Text vào cột “Supplier” (cột 3) và phần Value vào cột “SupplierID” (cột 6). Bạn sửa lại hai thủ tục cboSupplier_VisibleChanged và cboSupplier_SelectionChanged như sau:
Private Sub cboSupplier_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim cbo As ComboBox = sender
Dim rownum As Integer = dgdProducts.CurrentRowIndex
Dim intSupplierID As Integer = 0
Try
intSupplierID = dgdProducts.Item(rownum, 6).ToString()
Catch Err As Exception
'Do nothing here
Finally
cbo.SelectedValue = intSupplierID
End Try
End Sub
Private Sub cboSupplier_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim cbo As ComboBox = sender
Dim rownum As Integer = dgdProducts.CurrentRowIndex
'Set value to column "SupplierID"
dgdProducts.Item(rownum, 6) = cbo.SelectedValue
'Set value to unbound column "Supplier"
dgdProducts.Item(rownum, 3) = cbo.Text
End Sub
Bước 6: Cập nhật CSDL gốc
Đến đây bạn đã có một Datagrid.Net với giao diện hoàn chỉnh. Nhưng như bạn đã biết, ADO.Net là dạng disconnected nên những gì bạn sửa đổi ở trên giao diện chỉ có tác dụng khi bạn update CSDL gốc bằng một thủ tục tường minh. Thiết nghĩ các bạn quá rành việc này rồi (còn nếu chưa xin các bạn tham khảo các cuốn sách về VB.Net). Trong phần tutorial này tôi xin nhường cho các bạn viết thủ tục update này vì không muốn là hỏng CSDL Northwind.mdb.
Cảm ơn các bạn đã đọc.
Note: Bạn có thể download bài viết dạng .doc và sourcecode gởi kèm
3. Nắm Toàn Quyền Điều Khiển Giao Diện DataGrid.Net
Cho đến giờ, bạn đã có một Datagrid có Combobox ở cột SupplierID nhưng bạn không thể hiển thị tên của các Suppliers thay vì các ID, ngoài ra cấu trúc của các cột phụ thuộc vào cấu trúc của dataset. Bạn sẽ phải làm gì nếu muốn thay đổi thứ tự các cột (VD: đưa cột “Discontinued” lên đầu tiên?)
Bạn hãy xem giao diện được cải thiện như dưới đây:
(To see picture, download attached file)
So với phiên bản trước, phiên bản này có những cải tiến sau:
Các cột có thể di chuyển tới vị trí bất kỳ, không phụ thuộc vào cấu trúc của datasource (datatable) nữa. VD: Cột “Discontinued” được di chuyển lên vị trí đầu tiên.
Các header cột thể hiện tên tùy ý. VD: “Unit Price” thay vì “UnitPrice”.
Cột “Supplier” với tên đầy đủ của các nhà cung cấp thay cho cột “SupplierID” với những mã số kém trực quan.
Để thực hiện được việc này, trước hết chúng ta hãy xem qua một vài kỹ thuật có thể áp dụng được trong Datagrid.Net:
Datagrid.Net có hai dạng cột (column styles) có sẵn là Textbox (DataGridTextBoxColumn) và Checkbox (DataGridBoolColumn), bạn có thể tạo/thêm các cột này vào lúc thiết kế hay runtime. Nếu không, khi bạn gắn Datagrid vào CSDL, nó sẽ tự tạo ra các cột tương ứng với các cột dữ liệu theo cấu trúc của Dataset, nếu các cột có dữ liệu dạng False/True thì sẽ được hiển thị trong DataGridBoolColumn còn các dạng khác sẽ bị biến thành dạng text hết và hiển thị trong DataGridTextBoxColumn. Ngoài ra, bạn có thể tự tạo ra các column style khác (custom) và gắn vào datagrid (tôi sẽ đề cập tới vấn đề này trong một bài khác).
Các cột của Datagrid.Net có thể gắn kết với một cột dữ liệu (bound) hay hoàn toàn độc lập với CSDL. Để gắn chính xác một cột của Datagrid.Net với một cột trong datatable, ta sẽ sử dụng kỹ thuật Mapping Name - nghĩa là gán tên cột dữ liệu vào cột của Datagrid.
Ngoài ra ta cũng có thể thêm các cột dữ liệu unbound vào Datatable, các cột này sẽ không dùng để update CSDL chính mà chỉ dùng để thể hiện các dữ liệu theo ý của bạn.
Hình thức thể hiện (màu sắc, font chữ...) của Datagrid.Net có thể thay đổi thông qua các DataGridTableStyle gắn kết với nó. Xin các bạn xem lại đoạn code tạo và sử dụng TableStyle trong Phần I (ở thủ tục PopulateGrid()):
[/list=1]
If (Not dgdProducts.TableStyles.Contains("Products")) Then
'Create a DataGridTableStyle object
Dim dgdtblStyle As New DataGridTableStyle()
'Set its properties
dgdtblStyle.MappingName = tblProducts.TableName 'its table name of dataset
dgdProducts.TableStyles.Add(dgdtblStyle)
dgdtblStyle.AlternatingBackColor = Color.Yellow
dgdtblStyle.AllowSorting = True
dgdtblStyle.RowHeadersVisible =
dgdtblStyle.HeaderFont = New System.Drawing.Font("Microsoft Sans Serif", 9.0F, System.Drawing.FontStyle.Bold, GraphicsUnit.Point, 0)
dgdtblStyle.GridLineColor = Color.DarkGray
dgdtblStyle.PreferredRowHeight = 22
dgdProducts.BackgroundColor = Color.White
End If
Bây giờ chúng ta hãy bắt tay vào tạo dựng Datagrid của mình.
Bước 1: Thêm cột unbound “Supplier” vào datatable tblProducts
Trong thủ tục PopulateGrid(), sau phần tạo Combobox bạn thêm đoạn mã sau:
'Add an unbound column that comtain Combobox to main datatable
Dim dcolCombo As DataColumn
dcolCombo = New DataColumn("Supplier")
With dcolCombo
.DataType = System.Type.GetType("System.String")
.DefaultValue = ""
End With
tblProducts.Columns.Add(dcolCombo)
Lúc này cột dữ liệu mới thêm vào hoàn toàn trống rổng, bạn phải fill dữ liệu – tên các supplier – vào bằng cách gọi thủ tục:
FillUnboundColumn()
và viết code để fill tên Supplier tương ứng với SupplierID trong bảng “Products”. Hai thủ tục/hàm sau sẽ giúp bạn thực hiiện điều này:
Private Sub FillUnboundColumn()
Dim i As Integer
Dim dRow As DataRow
'Go to each row of unbound column "Supplier" and fill with meaningful data
For i = 0 To tblProducts.Rows.Count - 1
dRow = tblProducts.Rows(i)
'Fill "Supplier" column with supplier name inaccordance with SupplierID
dRow("Supplier") = FindSupplierName(dRow("SupplierID"))
Next
'Set default value for "SupplierID" column, so that when you add new row
'the Datagrid will behave correctly
tblProducts.Columns("SupplierID").DefaultValue = 1
End Sub
Private Function FindSupplierName(ByVal ID As Integer) As String
Dim i As Integer
Dim dRow As DataRow
For i = 0 To tblSuppliers.Rows.Count - 1
dRow = tblSuppliers.Rows(i)
If dRow(0) = ID Then
Return dRow(1).ToString
End If
Next
End Function
Bước 2: Tạo mới các column trong Datagrid
Như vậy hiện giờ tblProducts có 7 cột dữ liệu, để thể hiện chúng theo ý mình, bạn cần tạo ra 7 cột tương ứng trong Datagrid. Nếu bạn muốn cột đó có chứa CheckBox thì bạn tạo loại cột DataGridBoolColumn, còn không bạn tạo dạng DataGridTextBoxColumn. Ở đây ta muốn đưa cột “Discontinued” là dạng False/True lên đầu tiên để tiện theo dõi những hàng nào không còn đặt mua nữa. Ta thêm đoạn code sau vào ngay sau phần tạo và format DataGridTableStyle vừa trình bày ở trên:
Private Sub PopulateGrid()
…
If (Not dgdProducts.TableStyles.Contains("Products")) Then
…
Dim i As Integer
For i = 0 To 6
If i <> 0 Then
Dim gridcol As New DataGridTextBoxColumn()
dgdtblStyle.GridColumnStyles.Add(gridcol)
Else
Dim gridcol As New DataGridBoolColumn()
dgdtblStyle.GridColumnStyles.Add(gridcol)
End If
Next
End If
End Sub
Bước 3: Gán các cột trong datatable tblProducts vào các cột của Datagrid.Net
Sau khi tạo ra các cột, việc tiếp theo là chúng ta phải làm cho Datagrid hiểu cột nào sẽ thể hiện dữ liệu của cột nào trong datatable và định ra header text, chiều rộng của các cột. Thêm vào phần code như dưới đây:
Private Sub PopulateGrid()
...
If (Not dgdProducts.TableStyles.Contains("Products")) Then
...
...
'Mapping datagrid columns to column names of “tblProducts” and
'format header text and column width.
Dim colStyle As GridColumnStylesCollection
colStyle = dgdProducts.TableStyles(0).GridColumnStyles
colStyle(0).MappingName = "Discontinued"
colStyle(0).HeaderText = "Discontinued"
'
colStyle(1).MappingName = "ProductID"
colStyle(1).HeaderText = "Product ID"
'
colStyle(2).MappingName = "ProductName"
colStyle(2).HeaderText = "Product Name"
colStyle(2).Width = 150
'
colStyle(3).MappingName = "Supplier"
colStyle(3).HeaderText = "Supplier"
colStyle(3).Width = "150"
'
colStyle(4).MappingName = "QuantityPerUnit"
colStyle(4).HeaderText = "Quantity"
'
colStyle(5).MappingName = "UnitPrice"
colStyle(5).HeaderText = "Unit Price"
'
colStyle(6).MappingName = "SupplierID"
colStyle(6).Width = 0
End If
'To add the combo box dynamically to the data grid, you have to take the
'Text Box that is present (by default) in the column where u want to add
'this combo box (here it is third column i.e. Supplier).From the
'tablestyles of the data grid take the grid column styles of the column
'where you want to add the combo box respectively.
Dim dgtb As DataGridTextBoxColumn = dgdProducts.TableStyles(0).GridColumnStyles(3)
'Add the combo box to the text box taken in the above step
dgtb.TextBox.Controls.Add(cboSupplier)
'Set DataGrid source as the table "Products"
dgdProducts.DataSource = tblProducts
End Sub
=>Ở đây bạn lưu ý hai điểm sau:
[list]
Cột SupplierID được đưa ra sau cùng và có chiều rộng là 0, nghĩa là người sử dụng sẽ không thấy được cột này.
Bạn phải đặt DataSource cho datagrid sau khi đã mapping name nếu không khi chạy chương trình sẽ báo lỗi là không thể Mapping name được vì tên này đã có rồi.
Bước 4: Bỏ qua hoàn toàn cột SupplierID
Mặc dù ở bước trên, bạn đã cho cột SupplierID ẩn dấu nhưng nó chưa thực sự “biến mất” hoàn toàn. Nếu bạn dùng tab di chuyển giữa các ô của Datagrid bạn sẽ nhận thấy nó vẫn dừng lại ở cột cuối cùng dù không nhìn thấy. Để bỏ qua cột này, chúng ta phải thêm một thủ tục để khi một cell trong cột này nhận focus nó sẽ chuyển ngay focus về cell của cột đầu tiên, hàng tiếp theo.
Muốn vậy, bạn thêm một handler điều khiển việc nhận focus của textbox trong cột SupplierID (cột 6). Gõ vào đoạn mã này vào cuối thủ tục PopulateGrid():
'Add handlers to control grid navigation so that all hided columns will be passed by
dgtb = dgdProducts.TableStyles(0).GridColumnStyles(6)
AddHandler dgtb.TextBox.GotFocus, AddressOf Col6_GotFocus
Và viết thủ tục Col6_GotFocus:
Private Sub Col6_GotFocus(ByVal sender As Object, ByVal e As EventArgs)
Dim colnum As Integer = dgdProducts.CurrentCell.ColumnNumber
If colnum <> 6 Then Exit Sub
'Set focus to the cell of first column, next row
Dim cell As New DataGridCell(dgdProducts.CurrentRowIndex + 1, 0)
dgdProducts.CurrentCell = cell
End Sub
Bước 5: Làm cho ComboBox cập nhật đúng dữ liệu
Khi bạn chọn một item mới trong ComboBox ở cột “Supplier”, ComboBox sẽ phải cập nhật phần Text vào cột “Supplier” (cột 3) và phần Value vào cột “SupplierID” (cột 6). Bạn sửa lại hai thủ tục cboSupplier_VisibleChanged và cboSupplier_SelectionChanged như sau:
Private Sub cboSupplier_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim cbo As ComboBox = sender
Dim rownum As Integer = dgdProducts.CurrentRowIndex
Dim intSupplierID As Integer = 0
Try
intSupplierID = dgdProducts.Item(rownum, 6).ToString()
Catch Err As Exception
'Do nothing here
Finally
cbo.SelectedValue = intSupplierID
End Try
End Sub
Private Sub cboSupplier_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim cbo As ComboBox = sender
Dim rownum As Integer = dgdProducts.CurrentRowIndex
'Set value to column "SupplierID"
dgdProducts.Item(rownum, 6) = cbo.SelectedValue
'Set value to unbound column "Supplier"
dgdProducts.Item(rownum, 3) = cbo.Text
End Sub
Bước 6: Cập nhật CSDL gốc
Đến đây bạn đã có một Datagrid.Net với giao diện hoàn chỉnh. Nhưng như bạn đã biết, ADO.Net là dạng disconnected nên những gì bạn sửa đổi ở trên giao diện chỉ có tác dụng khi bạn update CSDL gốc bằng một thủ tục tường minh. Thiết nghĩ các bạn quá rành việc này rồi (còn nếu chưa xin các bạn tham khảo các cuốn sách về VB.Net). Trong phần tutorial này tôi xin nhường cho các bạn viết thủ tục update này vì không muốn là hỏng CSDL Northwind.mdb.
Cảm ơn các bạn đã đọc.