Bài 14
DataGrid (phn II)
Dùng Dataview để Filter và Sort
Thường thường, khi điu khin trong thi gian tht (real-time control), là
Operator, ta mun các alarms có ưu tiên cao và mi xãy ra nht được hin
th trên hết. Đôi khi, ta ch mun thy các alarm priority 3 (ưu tiên cao
nht) mà thôi. Để thc hin các vic ny, ta dùng Dataview Object.Thay
vì dùng thng table alarm ca DataSet alarmlist làm datasource ca
DataGrid1, ta s dùng mt DataView derived from (đến t) table alarm. Ta
có th Sort (sp theo th t) các alarms/records theo Priority hay áp dng
Filter (sàn lc) vào DataView để ch thy nhng th gì mình mun, thí d
ch có alarms priority 3 thôi.Nên nh là nm đàng sau vn là table alarm,
nhưng Dataview đóng vai trò cp kiếng mát màu giúp cho ta thy nhng
th gì và theo cách ta mun. Mi khi ta thay mt cp kiếng, ta li thy
nhng th khác.Dưới đây là Sub BtnLoadXMLData_Click được sa li mt
chút để dùng DataView:
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
' Create a Dataview from DS
DV1 = New System.Data.DataView(DS.alarm)
' Sort alarms by priority, then datetime
' DESC stands for descending order,i.e. biggest on
top
DV1.Sort = "priority DESC, datetime DESC"
' Bind the Datagrid DataSource to Dataview
DataGrid1.DataSource = DV1
AddCustomDataTableStyle()
' Display the number of alarms in each priority
DisplayTotal()
End Sub
Để ý Dataview object DV1 được derived t DS.alarm. Sau đó ta Sort các
alarms theo th t ưu tiên, ri trong s nhng alarm có cùng priority ta li
Sort chúng theo datetime ( đây data type ca datetime ch
string).Ngoài ra để đếm con s các alarms thuc mi priority ta có th
dùng Dataview vi filter ri xem property Count ca nó như sau:
Private Sub DisplayTotal()
' Create a Dataview object from table DS.alarm
Dim DVP1 As New System.Data.DataView(DS.alarm)
' Apply filter
DVP1.RowFilter = "priority = 1"
' Display Count of records in this Dataview
NumPrio1.Text = "Prio1: " & DVP1.Count.ToString
Dim DVP2 As New System.Data.DataView(DS.alarm)
DVP2.RowFilter = "priority = 2"
NumPrio2.Text = "Prio2: " & DVP2.Count.ToString
Dim DVP3 As New System.Data.DataView(DS.alarm)
DVP3.RowFilter = "priority = 3"
NumPrio3.Text = "Prio3: " & DVP3.Count.ToString
NumTotal.Text = "Total: " &
DS.alarm.Rows.Count.ToString
Dim bmb As BindingManagerBase =
Me.BindingContext(DataGrid1.DataSource,
DataGrid1.DataMember)
NumDisplayed.Text = "Displayed: " &
bmb.Count.ToString
End Sub
Chc bn đã để ý thy thay vì iterate qua mi record để đếm con s
alarms thuc priority 1,2 hay 3, ta đã dùng ba Dataviews để filter ra
alarms thuc ba priorities khác nhau ri ly tr s Count ca mi Dataview.
Đây là li lp trình da vào nhng gì có sn càng nhiu càng tt để tránh
to ra bugs.Ngoài ra, để đếm con s hàng alarms được tht s hin th bt
c lúc nào ta dùng BindingManagerBase object trong hai hàng code
dưới đây:
Dim bmb As BindingManagerBase =
Me.BindingContext(DataGrid1.DataSource,
DataGrid1.DataMember)
NumDisplayed.Text = "Displayed: " & bmb.Count.ToString
Ta đặt thêm ba buttons để filter alarms vi code sau đây:
Private Sub Btn1and2_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) _
Handles Btn1and2.Click
DV1.RowFilter = "priority < 3"
Dim bmb As BindingManagerBase =
Me.BindingContext(DataGrid1.DataSource,
DataGrid1.DataMember)
NumDisplayed.Text = "Displayed: " &
bmb.Count.ToString
End Sub
Private Sub Btn1Only_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) _
Handles Btn1Only.Click
DV1.RowFilter = "priority = 1"
Dim bmb As BindingManagerBase =
Me.BindingContext(DataGrid1.DataSource,
DataGrid1.DataMember)
NumDisplayed.Text = "Displayed: " &
bmb.Count.ToString
End Sub
Private Sub BtnAllAlarms_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) _
Handles BtnAllAlarms.Click
DV1.RowFilter = ""
Dim bmb As BindingManagerBase =
Me.BindingContext(DataGrid1.DataSource,
DataGrid1.DataMember)
NumDisplayed.Text = "Displayed: " &
bmb.Count.ToString
End Sub
Bn có th chay chương trình và bm các nút va mi thêm vào để xem
các alarms được filtered như thế nào.
Làm vic vi mt Row trong DataGrid
Khi mt alarm mi được báo cáo và hin th, h thng điu khin real-time
thường hay phát ra nhng tiếng Beep nho nh để nhc Operator x s
c to ra alarm. Vic đầu tiên Operator s làm là Acknowledge (xác
nhn là tôi biết ri, kh lm, nói mãi!) cái alarm bng cách right click lên
Row hin th alarm ri click menuCommand Acknowledge t
PopupMenu.Khi bn đã Acknowledge mt alarm ri thì cái ACKN checkbox
s được đánh du và nếu h thng không còn alarm nào chưa được
acknowledged thì nó s ngng Beep. Ngoài ra, có khi vì bn biết là lý do
gây ra mt alarm nào đó không quan trng (thí d nhân viên k thut
đang sa và th cái sensor ca alarm y) và bn không mun alarm y
được báo cáo trong tương lai, bn có th Isolate (cô lp hóa) nó. Khi nào
mun cho nó hot động bình thường tr li, bn s Enable (tác động)
nó.Bây gi bn hãy đặt mt ContextMenu control vào form và Edit cho nó
ba menuCommands tên mnuAckn(Acknowledge),
mnuIsolate(Isolate)mnuEnable(Enable) như trong hình dưới đây:
Mi khi user right click lên mt hàng alarm, ContextMenu1 s hin th ch
nhng menuCommands thích hp vi tình hung. Tc là nếu alarm chưa
được acknowledged thì mi có menuCommand Acknowledge, khi alarm
chưa b isolated thì mi có menuCommand Isolate, nếu đã b isolated ri
thì ch có MenuCommand Enable.Bình thường, nếu bn click lên mt
checkbox còn trng trong DataGrid1, checkbox y s được đánh du.
Nhưng trong chương trình ca chúng ta ti đây ta không mun cho user
làm vic y mà phi Acknowlege, Isolate hay Enable bng PopupMenu. Do
đó bn hãy cho property ReadOnly ca DataGrid1 bng True.Lúc
chương trình nhn được Event MouseDown t DataGrid1 ta s tìm cách
xác định lúc by gi Mouse đang nm trên alarm line nào bng cách chy
Method HitTest ca DataGrid1. Khi DataGrid1 HitTest v trí ca Mouse vi
instruction myGrid.HitTest(e.X, e.Y), nó s cho ta mt Object
HitTestInfo. Property Row ca HitTestInfo là hàng th my trong
DataGrid1. Để ly ra đúng DataRowView nào đang hin th
HitTestInfo.Row y ta phi da vào BindingManagerBase. Cái
DataRowView mà ta đang tìm chính là DataRowView ca
BindingManagerBase vi position bng HitTestInfo.Row y.Trong chương
trình ny, ta s cha DataRowView y trong variable drv. Dưới đây là
code để x lý Event MouseDown ca DataGrid1, để ý là ta hin th bên
dưới cái description ca alarm được clicked bng statement
Label1.Text = drv("description") để cho user mt feedback:
' Variable used to store selected DataRowView