DataGrid trong .NET tuy có các chức năng giống như trong
VB6 nhưng đã được nâng cấp vượt bực và cách dùng thay đổi rất nhiều nên coi
như ta phải học lại từ đầu.
Cách dùng thông thường nhất của một
DataGrid trong VB6 là hiển thị một Table các records trong dạng một
spreadsheet, mỗi hàng (row) chứa các datafields của một record và mỗi
cột (column) có header cho biết là datafield gì.
Nói cho đúng
ra, nằm sau lưng mỗi DataGrid là một Recordset, tức là một Set of
Records mà ta chọn lấy từ database. Table chẳng qua cũng là một
Recordset trong trường hợp tổng quát khi ta không dùng Clause WHERE
trong SQL command, thí dụ như "Select * from Authors".
Trong .NET, ý niệm
Recordset đã được thay thế bằng Dataset. Trong một bài tới ta sẽ học
chi tiết về Data Access trong VB.NET, nên hiện giờ chỉ cần biết đại
khái về Dataset để dùng trong các thí dụ áp dụng DataGrid.
Trong
ADO (ActiveX Data Object) của VB6 ta dùng Connection để nối
chương trình áp dụng của mình với cơ sở dữ liệu và lấy ra một Recordset. Cái
connection ấy vẫn được giữ nguyên trong khi chương trình ta làm việc với
Recordset. Trong ADO.NET của .NET sau khi thiết lập connection với cơ
sở dữ liệu ta copy một hay nhiều Recordset vào Dataset. Các Recordset nầy có
thể có mối liên hệ Master/Slave Relation với nhau. Thí dụ như
Invoice/InvoiceDetails, trong đó các InvoiceDetails liên hệ với Invoice qua
InvoiceID chẳng hạn, tức là InvoiceID là Primary Key của Invoice và cũng là
Foreign Key của InvoiceDetails . Sau đó ta chỉ làm việc với Dataset mà thôi.
Cái connection coi như đã bị cắt đứt. Do đó Dataset được xem như là
disconnected database nho nhỏ nằm trong bộ nhớ.
Chắc chắn bạn
sẽ không an lòng và hỏi nếu có hai người cùng copy các Recordset ra dùng thì
liệu khi update ta có bị mất những sửa đổi nào không. Đó là vấn đề khó khăn
cổ điển về Multiuser lúc hai người copy cùng một record ra để Edit. Người
Update record sau có thể viết chồng lên Edited Record của người trước khiến
cho những thay đổi người trước đánh vào bị mất.
Cái hay của ADO.NET
là khi ta muốn Update Dataset, connection sẽ được tự động nối lại và dataset
sẽ được reconciled với cơ sỡ dữ liệu. Chữ reconcile là một từ
kỹ thuật trong kế toán mà ta hay dùng để nói đến việc so sánh các chi tiết
tiền ra vô của một trương mục giữa sổ sách chúng ta giữ và bảng báo cáo của
nhà băng để điều chỉnh lại các con số trong sổ sách của chúng ta cho giống
như của nhà băng. Nếu ta giữ sổ sách chính xác thì sự khác biệt chỉ là những
transactions (món tiền ra, vô) nhà băng làm mà ta chưa biết như chi phí dịch
vụ của nhà băng, thuế tài chánh .v.v.. Bên trong Dataset có chứa các trị số
cũ của datafields để dùng vào việc so sánh khi Reconcile các
records.
Có lẽ bạn thắc mắc tại sao Microsoft lại bày đặt thêm ra
chuyện ADO.NET với ý niệm disconnected database chi cho mệt, như có người
trào phúng: "Mỗi năm lại thêm một kỹ thuật mới về Data Access từ
Microsoft". Lý do chính là để áp dụng trong Internet. Vì mọi connection
trên mạng đều nhất thời, sau khi hoàn tất transaction thì hai bên chia tay
tạm biệt. Do đó rất khó cho ta giữ một connection thường trực như trong ADO.
Nên nhớ rằng sau nầy lần lần các áp dụng trên Internet sẽ thay thế các giải
pháp (Applications) ta dùng trong mạng cục bộ. Ngay cả nếu chỉ muốn dùng
Application trong nội bộ ta cũng có thể dùng Intranet. Như thế ta chỉ cần
triển khai một Application duy nhất để dùng cho cả người ngoài (Internet),
lẫn nội bộ (Intranet).
Dataset của ADO.NET cho ta các lợi ích thực
tiển như:
Hoàn toàn trong bộ nhớ: Một Table trong Dataset là một Array of Rows, nên ta có thể dùng thẳng (direct access) một record bằng cách nói đến cái Row chứa nó, chớ không cần phải dùng MoveNext, MovePrev,.v.v.
Làm nhẹ công tác của cơ sỡ dữ kiện chính: Vai trò của Dataset đối với cơ sỡ dữ kiện chính (Oracle, Informix, SQLServer .v.v.) cũng giống như mười năm trước đây ta bắt đầu dùng Workstations để làm nhẹ công tác của Mainframe computer. Chuyện nào Workstation làm được thì ta giao cho nó, vừa nhanh, vừa linh động, khỏi cần phiền đến Mainframe. Tất cả mọi công tác sửa đổi dữ kiện đều được thực hiện trong Dataset.
Dataset có thể được biểu diển bằng một XML (eXtensible Marked Language): Ta có thể dùng các công cụ của XML để làm việc với Dataset, trao đổi Dataset giữa các computers trên mạng dưới dạng XML, thậm chí có thể chứa một cơ sở dữ kiện nho nhỏ dưới dạng một XML.
Chúng ta
muốn hiển thị các records của một Table trong Dataset để biểu diễn các chức
năng của DataGrid. Hôm nay mình chơi nổi, nên sẽ tạo một XML file để dùng nó
làm một Dataset, thay vì trích một Table từ một SQLServer hay Access
database.
Trước hết bạn hãy khởi động một dự án mới, đặt tên nó là
AlarmList. Kế đó, trong Solution Explorer rename tên của file
Form1.vb thành frmAlarmList.vb và thay đổi property Text của
form thành Alarm List, property Name của form thành
frmAlarmList.

Lưu ý là chỉ khi bạn thay đổi property Name của form bạn
mới thấy tên của Class của form thay đổi từ Form1 ra
frmAlarmList như ta thấy trong hình dưới đây:
Nếu bây giờ bạn right click lên tên của project
AlarmList trong Solution Explorer và chọn PopupMenuItem Properties,
dialog AlarmList Property Pages hiện ra. Trong ComboBox của
Startup object vẫn còn có chữ Form1. Bạn có thể click lên cái
cái tam giác bên phải của hộp Combobox để select chữ frmAlarmList để
chỉ định nó làm Startup form.

Trong chương trình
nầy ta lo về an ninh và muốn hiển thị các cánh cửa trong tòa nhà bị mở cửa
ngoài giờ làm việc. Nếu áp dụng ngoài đời thì Real-time Data sẽ được thu
thập từ các dụng cụ gọi là Data Acquisition hay Telemetry Monitoring Devices
và báo cáo cho hệ thống trung ương để cập nhật hóa Dataset mà ta dùng để
hiển thị trong DataGrid.
Bạn hãy click IDE menu command Project |
Add New Item rồi chọn XML File và đặt tên nó là
AlarmList.xml như trong hình dưới đây:
Kế đó ta sẽ đánh vào data của AlarmList. Hàng đầu của XML file là một Processing Instruction (huấn thị cách xử lý) tuyên bố rằng ta dùng tiêu chuẩn xml version 1.0 với Unicode encoding utf-8.
<?xml version="1.0" encoding="utf-8"?> |
Phần chính của cả cái XML file nằm
giữa cặp Tag <alarmlist> (gọi là opening Tag) và
</alarmlist> (gọi là closing Tag). Ta gọi alarmlist là
Element. Bên trong chính alarmlist là nhiều Elements tên
alarm. Các Element alarm không cần có closing Tag vì chúng không có
chứa gì bên trong. Trong trường hợp nầy ta chấm dứt opening Tag bằng />. Tuy nhiên mỗi Element alarm có chứ nhiều
Attributes như priority, datetime, pointid .v.v.. bên trong opening
Tag của nó. Mỗi Attribute có dạng
TêncủaAttribute="valuecủaAttribute". Lưu ý valuecủaAttribute nằm giữa
dấu ngoặc kép hay ngoặc đơn.
<alarmlist> <alarm priority="3" datetime="20/7/2001 16:33:11" pointid="401-2-9" description="Level 1 backroom door" statusvalue="Open" diagram="19" alarm="true" isolate="false" fault="false" ackn="true"/> <alarm priority="3" datetime="20/7/2001 18:47:33" pointid="402-8-7" description="Level 1 kitchen side door" statusvalue="Open" diagram="6" alarm="true" isolate="false" fault="false" ackn="false"/> <alarm priority="2" datetime="20/7/2001 16:21:40" pointid="401-6-7" description="Side door of third level" statusvalue="Open" diagram="14" alarm="true" isolate="false" fault="false" ackn="true"/> <alarm priority="1" datetime="20/7/2001 15:19:37" pointid="401-2-3" description="Car park rear entrance" statusvalue="Open" diagram="16" alarm="true" isolate="false" fault="false" ackn="false"/> <alarm priority="1" datetime="20/7/2001 17:18:27" pointid="401-1-3" description="Front door of tenth level" statusvalue="Open" diagram="25" alarm="true" isolate="false" fault="false" ackn="true"/> <alarm priority="2" datetime="20/7/2001 16:21:30" pointid="401-5-4" description="Back door of nineth level" statusvalue="Open" diagram="5" alarm="true" isolate="false" fault="true" ackn="false"/> </alarmlist> |
Bây giờ click MenuCommand
XML | Create Schema như dưới đây:
Chú ý là MenuCommand XML chỉ hiện ra khi ta làm việc
với XML file của project (doubleclick tên AlarmList.xml trong Solution
Explorer). Một Schema của file AlarmList.xml, tên AlarmList.xsd, sẽ
hiện ra trong Solution Explorer và bạn có thể doubleclick tên AlarmList.xsd
để làm việc với file ấy.
.NET IDE cho ta hình của Schema để ta có thể
Edit dễ dàng. Thông thường, IDE chỉ xác nhận thứ nào là Element (có chữ
E nằm bên trái), thứ nào là Attribute (có chữ
A nằm bên trái). Còn về Datatype thì nó nhắm
mắt nói mọi thứ là string. Do đó ta phải sửa đổi lại theo ý mình, để
nói Attribute priority là integer và các Attributes alarm, isolate,
fault, ackn là Boolean.
AlarmList.xsd cũng là một XML file, nó chứa chi tiết về cấu trúc của AlarmList.xml và Datatype (loại data ) của từng Element và Attribute trong file AlarmList.xml. Nếu bạn click Tab XML kế bên Tab DataSet phía dưới bạn sẽ thấy hình dưới đây:
Bây giờ click trở lại Tab DataSet, đoạn dùng MenuCommand Schema | Generate Dataset để tạo ra cấu trúc của một DataSet dựa vào Schema AlarmList.xsd.
Một file tên AlarmList.vb sẽ được tạo ra trong
source code folder của project. Nó định nghĩa và cung cấp mọi method cần
thiết để dùng cho DataSet loại alarmlist.
Dùng DataGrid
Để hiển thị data trong DataGrid, ta có thể bind (buộc) nó vào Dataset, Array hay Collection. Thật ra, nếu bạn muốn, bạn có thể câu cả DataGrid vào một Set của Listbox Items. DataGrid trong .NET có thể hiển thị cả Master/Detail records nên nó đảm nhận luôn chức năng của MSHFlexGrid trong VB6.
Ta hãy trở lại form frmAlarmList. Đặt lên nó một DataGrid
tên DataGrid1 và thêm một Button tên BtnLoadXMLData với Text
Load XML Data. Doubleclick lên Button BtnLoadXMLData để cho vào các
hàng codes sau đây:
' Declare a Dataset of type alarmlist from AlarmList.vb that was created from the schema AlarmList.xsd
Dim DS As alarmlist
Private Sub BtnLoadXMLData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles BtnLoadXMLData.Click
' Instantiate a DataSet type alarmlist
DS = New alarmlist()
' Load the XML data from file AlarmList.xml in the source code folder. Note that the program EXE resides
' in the bin subfolder
DS.ReadXml("../AlarmList.xml")
' Bind the Datagrid DataSource to this new DataSet table alarm
DataGrid1.DataSource = DS.alarm
End Sub
|
Bây giờ bạn có thể chạy chương trình của chúng ta. Click nút Load XML Data bạn sẽ thấy như sau:
Trong hình trên tất cả datafields của mỗi record được hiển thị với cùng bề ngang và với datafield name của chúng dùng làm đề tựa của mỗi cột. Ta có thể dùng DataGridTableStyle object để hiển thị các cột data theo ý mình bằng cách gọi Sub AddCustomDataTableStyle() (có code liệt kê dưới đây) trong Sub BtnLoadXMLData_Click.
Private Sub AddCustomDataTableStyle() ' Instantiate a DataGridTableStyle object Dim ts1 As New DataGridTableStyle() ts1.MappingName = "alarm" ' Name of data table ts1.AlternatingBackColor = Color.Beige ' Make alternating row beige ts1.RowHeadersVisible = False ' Make RowHeaders (on the left of DataGrid) invisible ' Only two types are supported: Text and Boolean ' Add the display field in order of display from left to right 'Just ignore a datafield if you don't want to display it Dim boolCol1 As New DataGridBoolColumn() ' Boolean boolCol1.MappingName = "ackn" ' Name of datafield boolCol1.HeaderText = "Ackn" boolCol1.Width = 35 ts1.GridColumnStyles.Add(boolCol1) ' Dim TextCol1 As New DataGridTextBoxColumn() ' Text TextCol1.MappingName = "priority" TextCol1.HeaderText = "Prio" TextCol1.Width = 30 ts1.GridColumnStyles.Add(TextCol1) ' Dim TextCol2 As New DataGridTextBoxColumn() TextCol2.MappingName = "datetime" TextCol2.HeaderText = "Time" TextCol2.Width = 110 ts1.GridColumnStyles.Add(TextCol2) ' Dim boolCol2 As New DataGridBoolColumn() boolCol2.MappingName = "alarm" boolCol2.HeaderText = "ALM" boolCol2.Width = 30 ts1.GridColumnStyles.Add(boolCol2) ' Dim boolCol3 As New DataGridBoolColumn() boolCol3.MappingName = "isolate" boolCol3.HeaderText = "ISO" boolCol3.Width = 30 ts1.GridColumnStyles.Add(boolCol3) ' Dim boolCol4 As New DataGridBoolColumn() boolCol4.MappingName = "fault" boolCol4.HeaderText = "FLT" boolCol4.Width = 30 ts1.GridColumnStyles.Add(boolCol4) ' Dim TextCol3 As New DataGridTextBoxColumn() TextCol3.MappingName = "pointid" TextCol3.HeaderText = "PointID" TextCol3.Width = 70 ts1.GridColumnStyles.Add(TextCol3) ' Dim TextCol4 As New DataGridTextBoxColumn() TextCol4.MappingName = "description" TextCol4.HeaderText = "Description" TextCol4.Width = 210 ts1.GridColumnStyles.Add(TextCol4) ' Dim TextCol5 As New DataGridTextBoxColumn() TextCol5.MappingName = "statusvalue" TextCol5.HeaderText = "Status/Value" TextCol5.Width = 150 ts1.GridColumnStyles.Add(TextCol5) ' Dim TextCol6 As New DataGridTextBoxColumn() TextCol6.MappingName = "diagram" TextCol6.HeaderText = "Diag" TextCol6.Width = 40 ts1.GridColumnStyles.Add(TextCol6) ' Now add the DataGridTableStyle object to Collection TableStyles of Datagrid1 DataGrid1.TableStyles.Add(ts1) End Sub
Trong code bên trên, ta
thấy DataGridTableStyle tên ts1 chứa một collection of
GridColumnStyles. Muốn hiển thị datafield nào của record ta tạo cho
nó một cột hoặc là Text hoặc là Boolean. Nếu là Text thì ta
instantiate một object loại DataGridTextBoxColumn, nếu là Boolean thì
ta instantiate một object loại
DataGridBoolColumn.
MappingName của
DataGridTextBoxColumn hay DataGridBoolColumn là tên của Datafield.
HeaderText là Tiêu đề nằm phía trên của cột datafield ấy.
Width là bề ngang của cột mà bạn phải thí nghiệm các con số vài lần
cho nó hiển thị vừa vặn.
Cột nào ta cho vô trước thì hiển thị bên
trái, vô sau thì nằm bên phải. Nếu ta cố ý không nhắc đến một datafield nào,
thì nó không được hiển thị. Sau khi chuẩn bị DataGridTableStyle đầy đủ rồi,
ta cho nó vào Collection TableStyles của DataGrid1.
Kế đó Edit
property Text của DataGrid1 cho nó câu "Dùng DataGridTableStyle để hiển thị
theo ý mình". Chạy chương trình lại và click nút Load XML Data bạn sẽ
thấy như sau:
Bạn có thể tải về chương
trình AlarmList nầy tại đây.
|
Vovisoft © 2000. All rights reserved. | ||||
|
Last Updated: 29 th7 2002 |
|
|||
PcLeHoan
1996 - 2002
Mirror :
http://www.pclehoan.com
Mirror :
http://www.lehoanpc.net
Mirror :
http://www.ktlehoan.com