[VB.NET] การสร้างหน้าจอ GUI ของการขายสินค้า แบบกราฟิค หรือโหมดทัชสกรีน
http://www.g2gsoft.com/webboard/images/VBNet/detaildatagridviewgui.jpgการสร้างหน้าจอ GUI ของการขายสินค้า แบบกราฟิค หรือโหมดทัชสกรีน ... โค้ดชุดนี้ถือว่าอยู่ในขั้นตอนของการออกแบบ จึงไม่มีการติดต่อเข้ากับระบบฐานข้อมูลใดๆ แต่อาศัยการใช้ข้อมูลสมมุติ หรือจำลอง ผ่านทาง DataTable ซึ่งจะมีการแบ่งกลุ่มหรือประเภทสินค้าเอาไว้ให้ 4 กลุ่ม และสามารถแสดงผลรายการสินค้าทั้งหมดออกมาได้ ...
ในการสร้าง Control ในลักษณะไดนามิค แบบนี้ (คือไม่รู้จำนวนรายการสินค้า หรือจำนวนกลุ่มที่แน่นอน) ก็ไม่ได้ยากเย็นมากนัก เริ่มจากการหาจำนวนกลุ่มสินค้าออกมาก่อน (ตัวอย่างมี 4 กลุ่ม + กลุ่มรวมทั้งหมด จะได้ 5 กลุ่ม) จากนั้นก็สร้าง TabPage และ Panel Control (เพื่อตีกรอบ Button Control ไม่ให้ล้น) มารองรับในแต่ละกลุ่ม เมื่อได้ Panel Control มาแล้ว ก็นำเอาจำนวนสินค้าที่อยู่ในแต่ละกลุ่มมาทำการแสดงผล โดยที่มีการคำนวณหาระยะของ Button อยู่ 2 ค่า คือ ...
1. หาค่าตำแหน่ง Left จะมาจากการหารเอาเศษ (MOD)
ตัวอย่างกำหนดเอาไว้ให้แสดงผลปุ่มคำสั่ง (Button) 3 หลัก
หาตำแหน่งซ้าย (Left) ... ด้วยการหารเอาเศษ (Mod) ด้วย 3 จะได้คำตอบ 0, 1, 2 ตลอด เพื่อใช้จัดวางตำแหน่งหลัก Button ได้ทีละ 3 หลัก
การหารเอาเศษจะได้ค่าสูงสุด คือ ค่าตัวหาร (Mod) ลบออก 1 เช่น X Mod 3 จะได้ค่า 0, 1, 2 (หรือ 3 - 1 = 2)
เริ่มนับจาก 0 ไปเรื่อยๆจนกว่าจะหมด (นับไปตามจำนวนรายการสินค้า)
0 Mod 3 = 0, 1 Mod 3 = 1, 2 Mod 3 = 2 ... รอบที่ 1
3 Mod 3 = 0, 4 Mod 3 = 1, 5 Mod 3 = 2 ... รอบที่ 2
6 Mod 3 = 0, 7 Mod 3 = 1, 8 Mod 3 = 2 ... รอบที่ 3 ... ทำไปเรื่อยๆ
มีคำตอบแค่ 0, 1, 2 เราก็เลยหาจำนวนหลักได้ตามที่กำหนด คือ 3 หลัก
เอาค่าที่ได้แต่ละหลักมาคูณความกว้างของปุ่มคำสั่ง
เป็นการเลื่อนตำแหน่งไปทางซ้าย ด้วยการคูณด้วย 0, 1 และ 2 เป็นจำนวนเท่าของความกว้างของ Button
B.Left = (iCount Mod ColCount) * B.Width
2. หาตำแหน่งบน (Top) ... ด้วยการหารตัดเศษ \ ... การหารปกติ 3 / 2 = 1.5, การหารตัดเศษ 3 \ 2 = 1
เริ่มนับจาก 0 ไปเรื่อยๆจนกว่าจะหมด (นับไปตามจำนวนรายการสินค้า)
0 \ 3 = 0, 1 \ 3 = 0, 2 \ 3 = 0 ... รอบที่ 1 (คำตอบคือ 0 เหมือนกัน)
3 \ 3 = 1, 4 \ 3 = 1, 5 \ 3 = 1 ... รอบที่ 2 (คำตอบคือ 1 เหมือนกัน)
6 \ 3 = 2, 7 \ 3 = 2, 8 \ 3 = 2 ... รอบที่ 3 (คำตอบคือ 2 เหมือนกัน) ... ทำไปเรื่อยๆ (คือการเพิ่มตัวคูณเข้าไปทีละ 1)
จะเห็นว่าหลักทั้ง 3 หรือ 3 ปุ่ม (Button) ในแต่ละแถว จะมีค่าคงที่ตลอด ไม่มีการเปลี่ยนค่าเลย จึงทำให้ตำแหน่ง Top ในแต่ละแถวเท่ากันเสมอ
เอาค่าที่ได้จากการหารตัดเศษในแต่ละแถว X (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล)
แถว 1 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 0 ดังนั้น Top = 0
แถว 2 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 1 ดังนั้น Top = (ความสูงของ Button+ความสูงของ Label) X 1
แถว 3 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 2 ดังนั้น Top = (ความสูงของ Button+ความสูงของ Label) X 2
B.Top = (iCount \ ColCount) * (B.Height + LB.Height)
มาดูโค้ดฉบับเต็มกันเถอะ ...Public Class frmFoodDrinkMain
'/ กำหนดตำแหน่งการเก็บไฟล์ภาพ ... โฟลเดอร์เก็บ Execute File\Images\
Dim strImagePath As String = MyPath(Application.StartupPath & "Images\")
' / --------------------------------------------------------------------------------
'/ ฟังค์ชั่นในการกำหนดพาธให้กับโปรแกรม
Private Function MyPath(ByVal AppPath As String) As String
MyPath = AppPath.ToLower.Replace("\bin\debug", "\").Replace("\bin\release", "\").Replace("\bin\x86\debug", "\")
'/ ASCII Code (92) = \ (Backslash)
If Microsoft.VisualBasic.Right(MyPath, 1) <> Chr(92) Then MyPath = MyPath & Chr(92)
End Function
' / --------------------------------------------------------------------------------
'/ Don't forget to set Form has KeyPreview = True
'/ เวลาทำการ Debugger ให้ปิด Handle ที่เหตุการณ์นี้
Private Sub frmFoodDrinkMain_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.F8
'/ Remove Row
Call DeleteRow("btnDelRow")
End Select
End Sub
' / --------------------------------------------------------------------------------
'// START HERE
Private Sub frmFoodDrinkMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.KeyPreview = True'/ สามารถกดปุ่มฟังค์ชั่นคีย์ลงในฟอร์มได้
Call InitializeGrid()
'// สร้าง TabPage แล้วตามด้วยสร้าง Panel จากนั้นให้สร้างปุ่มคำสั่ง (Button) ตามจำนวนรายการสินค้าที่อยู่ในแต่ละกลุ่ม/ประเภท
Call AddTabPage()
'//
txtSumTotal.ReadOnly = True
txtSumTotal.Text = "0.00"
lblLastPrice.Text = ""
End Sub
' / --------------------------------------------------------------------------------
'// เพิ่มแท็บเพจ (TabPage) คอนโทรลแบบไดนามิคลงไปใน TabControl1
' / --------------------------------------------------------------------------------
Private Sub AddTabPage()
Dim CatDataTable As New DataTable
'/ Remove First TabPage
Me.TabControl1.TabPages.Remove(TabPage1)
'// รับข้อมูลสมมุติมาจากตารางข้อมูล (DataTable) ในการจัดกลุ่ม/ประเภท (Category)
CatDataTable = GetCatDataTable()
'/ สร้าง Panel ตามจำนวนของกลุ่ม/ประเภท (Category) ในตัวอย่างมี 4 กลุ่ม และกลุ่มรวม (ALL) รวมเป็น 5 กลุ่ม
Dim pn(CatDataTable.Rows.Count)
Dim iCat As Byte = 0
' Loop and display the keys.
For Each CatRow As DataRow In CatDataTable.Rows
' / Create a tabpage
Dim tabPg As New TabPage
' / Set the tabpage to be your desired tab.
tabPg.Name = "Tab" & CStr(iCat)
'// แสดงชื่อกลุ่ม Category ใน TabPage
tabPg.Text = CatRow(1).ToString
'// เพิ่ม TabPage ลงใน TabControl1
Me.TabControl1.Controls.Add(tabPg)
'// เพิ่ม Panel
pn(iCat) = New Panel
pn(iCat).Name = "pn" & iCat
'/ สลับสีพื้นหลังของ Panel
With pn(iCat)
If (iCat Mod 2) = 0 Then
'/ เลขคู่แสดงสีนี้
.BackColor = Color.Beige
Else
'/ เลขคี่แสดงสีนี้
.BackColor = Color.PaleTurquoise
End If
'/ ปรับคุณสมบัติของ Panel แบบ Run-Time
.Dock = DockStyle.Fill
.Location = New System.Drawing.Point(1, 1)
.Size = New System.Drawing.Size(TabControl1.Width - 10, TabControl1.Height - 30)
.BackColor = Color.Moccasin
.AutoScroll = True
.Anchor = AnchorStyles.Bottom + AnchorStyles.Top
End With
'/ Add the panel into the TabControl
tabPg.Controls.Add(pn(iCat))
'/
Dim dt As New DataTable
dt = GetDataTable(CatRow(0).ToString)
' / --------------------------------------------------------------------------------
'/ ไปที่โปรแกรมย่อยการเพิ่มปุ่มคำสั่ง (Button)
'/ รอบแรกจะแสดงผลรายการสินค้าทั้งหมด เพราะส่งค่า 0 ออกไป ไม่ตรงกับค่ากลุ่มใดๆ
'/ กำหนด 3 หลัก, นับจำนวนรายการเพื่อทำปุ่ม, Panel(กลุ่ม/ประเภทสินค้า), DataTable
Call AddButton(3, dt.Rows.Count, pn(iCat), dt)
' / --------------------------------------------------------------------------------
iCat += 1
dt.Dispose()
Next
'/ ตั้งค่าที่แท็บเพจตัวแรก (ALL)
TabControl1.SelectedIndex = 0
CatDataTable.Dispose()
End Sub
' / --------------------------------------------------------------------------------
'// เพิ่มปุ่มคำสั่งแบบไดนามิค ตามจำนวนในแต่ละกลุ่ม/ประเภทสินค้า
' / --------------------------------------------------------------------------------
Private Sub AddButton(ByVal ColCount As Byte, ByVal btnCount As Byte, ByRef pn As Panel, ByRef dt As DataTable)
Dim iCount As Byte = 0
'/ วนรอบไปจนกว่าจำนวนปุ่ม (Button) มันเกินค่าที่มีอยู่
While btnCount <> iCount
Dim B As New Button
B.Height = 140
B.Width = 140
Dim LB As New Label
With LB
.Height = 40
.Width = 140
'// สลับสีของป้ายลาเบล
If iCount Mod 2 = 0 Then
'// เลขคู่
.BackColor = Color.Orange
Else
'// เลขคี่
.BackColor = Color.Crimson
End If
End With
pn.Controls.Add(B)'/ Add Button
pn.Controls.Add(LB) '/ Add Label อยู่ด้านล่างของ Button
'// Button
With B
' / ตัวอย่างกำหนดเอาไว้ให้แสดงผลปุ่มคำสั่ง (Button) 3 หลัก
' / --------------------------------------------------------------------------------
'// หาตำแหน่งซ้าย (Left) ... ด้วยการหารเอาเศษ (Mod) ด้วย 3 จะได้คำตอบ 0, 1, 2 ตลอด เพื่อใช้จัดวางตำแหน่งหลัก Button ได้ทีละ 3 หลัก
'// การหารเอาเศษจะได้ค่าสูงสุด คือ ค่าตัวหาร (Mod) ลบออก 1 เช่น X Mod 3 จะได้ค่า 0, 1, 2 (หรือ 3 - 1 = 2)
'// เริ่มนับจาก 0 ไปเรื่อยๆ
'// 0 Mod 3 = 0, 1 Mod 3 = 1, 2 Mod 3 = 2 ... รอบที่ 1
'// 3 Mod 3 = 0, 4 Mod 3 = 1, 5 Mod 3 = 2 ... รอบที่ 2
'// 6 Mod 3 = 0, 7 Mod 3 = 1, 8 Mod 3 = 2 ... รอบที่ 3 ... ทำไปเรื่อยๆ
'// มีคำตอบแค่ 0, 1, 2 เราก็เลยหาจำนวนหลักได้ตามที่กำหนด คือ 3 หลัก
'// เอาค่าที่ได้แต่ละหลักมาคูณความกว้างของปุ่มคำสั่ง
'// เป็นการเลื่อนตำแหน่งไปทางซ้าย ด้วยการคูณด้วย 0, 1 และ 2 เป็นจำนวนเท่าของความกว้างของ Button
.Left = (iCount Mod ColCount) * B.Width
' / --------------------------------------------------------------------------------
'/ Left ของ Button และ Label จะเท่ากัน
LB.Left = B.Left
' / --------------------------------------------------------------------------------
'// หาตำแหน่งบน (Top) ... ด้วยการหารตัดเศษ \ ... การหารปกติ 3 / 2 = 1.5, การหารตัดเศษ 3 \ 2 = 1
'// เริ่มนับจาก 0 ไปเรื่อยๆ
'// 0 \ 3 = 0, 1 \ 3 = 0, 2 \ 3 = 0 ... รอบที่ 1 (คำตอบคือ 0 เหมือนกัน)
'// 3 \ 3 = 1, 4 \ 3 = 1, 5 \ 3 = 1 ... รอบที่ 2 (คำตอบคือ 1 เหมือนกัน)
'// 6 \ 3 = 2, 7 \ 3 = 2, 8 \ 3 = 2 ... รอบที่ 3 (คำตอบคือ 2 เหมือนกัน) ... ทำไปเรื่อยๆ (คือการเพิ่มตัวคูณเข้าไปทีละ 1)
'// จะเห็นว่าหลักทั้ง 3 หรือ 3 ปุ่ม (Button) ในแต่ละแถว จะมีค่าคงที่ตลอด ไม่มีการเปลี่ยนค่าเลย จึงทำให้ตำแหน่ง Top ในแต่ละแถวเท่ากันเสมอ
'// เอาค่าที่ได้จากการหารตัดเศษในแต่ละแถว X (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล)
'// แถว 1 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 0 ดังนั้น Top = 0
'// แถว 2 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 1 ดังนั้น Top = (ความสูงของ Button+ความสูงของ Label) X 1
'// แถว 3 จึงคูณ (ความสูงของปุ่มคำสั่ง+ความสูงของลาเบล) ด้วย 2 ดังนั้น Top = (ความสูงของ Button+ความสูงของ Label) X 2
.Top = (iCount \ ColCount) * (B.Height + LB.Height)
' / --------------------------------------------------------------------------------
Dim row As DataRow = dt.Rows(iCount)
.Name = "Button" & row(0).ToString
.Text = "ID : " & row(1).ToString
'// นำค่า ProductPK (Primary Key) ไปซ่อนไว้ในคุณสมบัติ Tag ของ Button ในแต่ละตัว ซึ่งเราจะใช้ค่านี้เมื่อตอนคลิ๊กกดปุ่มคำสั่งในแต่ละตัว
'// เพื่อนำไปเปรียบเทียบค่าในตารางกริด (หลัก 0) หรือการค้นหาข้อมูลสินค้าด้วยค่า Primary Key
'// หรือใครที่กำหนดฟิลด์เอาไว้แค่ ID โดยไม่มี PK ... ก็ใช้ให้ ID ไปเลยก็ได้
.Tag = row(0).ToString
'// ทำการแสดงผลภาพลงบนปุ่ม
Dim imgFile As String = strImagePath & row(4).ToString
'/ ถ้าไม่ได้กำหนดรูป หรือหารูปภาพไม่เจอ ให้ใส่ภาพ NoImage.jpg ป้องกัน Error
If Not System.IO.File.Exists(imgFile) Then imgFile = strImagePath & "NoImage.jpg"
'/ นำภาพไปแสดงบน Button
.BackgroundImage = New System.Drawing.Bitmap(imgFile)
.BackgroundImageLayout = ImageLayout.Stretch
'/ ปรับคุณสมบัติ Button
.Font = New Font("Century Gothic", 10, FontStyle.Bold)
.ForeColor = Color.Black
.TextAlign = ContentAlignment.BottomCenter
.TextImageRelation = TextImageRelation.ImageAboveText
.UseVisualStyleBackColor = True
.Cursor = Cursors.Hand
.FlatStyle = FlatStyle.Standard
'// ปรับคุณสมบัติของ Label
With LB
.TextAlign = ContentAlignment.MiddleCenter
.Top = B.Top + B.Height
.ForeColor = Color.White
.Font = New Font("Tahoma", 10, FontStyle.Bold)
'/ Label ป้ายบอกเพื่อแสดงราคาใน Label
.Text = row(2).ToString & vbCrLf & "ราคา: " & Format(Convert.ToDecimal(row(3).ToString), "#,##0.00")
End With
End With
iCount += 1
' / --------------------------------------------------------------------------------
'// Event Handler ในการกดคลิ๊กที่ปุ่มคำสั่ง (Button)
AddHandler B.Click, AddressOf ClickButton
' / --------------------------------------------------------------------------------
End While
End Sub
' / --------------------------------------------------------------------------------
Public Sub ClickButton(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btn As Button = sender
'MessageBox.Show("Primary Key: " & btn.Tag)
'/ นำ Tag ซึ่งเก็บค่า ProductPK ไปใช้งานในการค้นหาสินค้า
Call AddToDataGridView(btn.Tag)
End Sub
' / --------------------------------------------------------------------------------
' / ค้นหารายการสินค้าของเดิมในตารางกริด ก่อนที่จะเพิ่มรายการแถวใหม่
' / อันนี้เขียนโค้ดกลับด้านกับเหตุการณ์ txtSearch_KeyPress
' / โดยใช้ค่า ProductPK (Primary Key ที่เป็นเลขจำนวนเต็ม) มาเปรียบเทียบกับค่าในตารางกริดก่อน
' / หากหาข้อมูลในตารางกริดไม่เจอ ก็จะไปค้นจาก DataTable อีกที
' / --------------------------------------------------------------------------------
Private Sub AddToDataGridView(ByVal PK As Integer)
Dim blnExist As Boolean = False
'// ตรวจสอบว่า Primary Key มีอยู่ในตารางกริดหรือไม่ (หากมีให้ +เพิ่ม, หากไม่มีค่อยไปค้นหาข้อมูล)
For iRow As Integer = 0 To dgvData.RowCount - 1
' / หากพบ Primary Key ในหลัก 0 มาตรงกันกับค่าในแถวของตารางกริด
' / ค่า Primary Key (PK) ตัวนี้ได้จากการกดปุ่ม (Button) โดยซ่อนค่าไว้ในคุณสมบัติ Tag ของ Button
If dgvData.Rows(iRow).Cells(0).Value = PK Then
' / ให้บวกจำนวนที่เลือกเพิ่มขึ้นอีก 1 (Quantity = Quantity + 1)
dgvData.Rows(iRow).Cells(3).Value = dgvData.Rows(iRow).Cells(3).Value + 1
'/ หลัก Index = 4 คือ UnitPrice
lblLastPrice.Text = "Last Price: " & Format(CDbl(dgvData.Rows(iRow).Cells(4).Value), "#,##0.00")
'// เจอข้อมูลเดิม
blnExist = True
'// ออกจากลูปไปเลย เพื่อไม่ให้เสียเวลา
Exit For
End If
Next
'// ไม่พบข้อมูลในตารางกริด ก็ทำการเรียกจากตารางข้อมูลเข้ามาแสดงผล
If Not blnExist Then
'/ สร้าง DataTable สมมุติขึ้นมา
Dim DT As DataTable = GetDataTable()
'/ ค้นหาข้อมูลจาก DataTable แล้วรับค่ามาใส่ไว้ใน DataRow
'/ การค้นหาข้อมูลแบบเลขจำนวนเต็ม เช่น ProductPK = 1
Dim r() As DataRow = DT.Select(" ProductPK = " & PK)
'// หากพบข้อมูลใน DataTable
If r.Count > 0 Then
'/ จากโครงสร้าง DataTable
'/ Primary Key, Product ID, Product Name, Quantity, UnitPrice, Total
dgvData.Rows.Add(r(0).Item(0), r(0).Item(1), r(0).Item(2), "1", Format(CDbl(r(0).Item(3).ToString), "0.00"), "0.00")
lblLastPrice.Text = "Last Price: " & CDbl(r(0).Item(3)).ToString("0.00")
End If
DT.Dispose()
End If
'// หาจำนวนเงินรวมใหม่
Call CalSumTotal()
'// โฟกัสไปที่ DataGridView แล้วย้ายไปแถวล่าสุด และไปทางซ้ายเพื่อไปที่ช่องจำนวน (Quantity)
'dgvData.Focus()
'SendKeys.Send("^{END}{LEFT}{LEFT}{LEFT}")
End Sub
' / --------------------------------------------------------------------------------
' / DataTable ของกลุ่ม/ประเภทสินค้า (Category)
' / --------------------------------------------------------------------------------
Function GetCatDataTable() As DataTable
Dim DT As New DataTable
With DT
.Columns.Add("CategoryPK", GetType(Byte)) '<<< Index = 0
.Columns.Add("CategoryName", GetType(String)) '<< Index = 1
End With
'// ... Add rows in the Category.
With DT
.Rows.Add(0, "ALL")
.Rows.Add(1, "Coffee")
.Rows.Add(2, "Burger")
.Rows.Add(3, "Soft Drink")
.Rows.Add(4, "Beverages")
End With
Return DT
End Function
' / --------------------------------------------------------------------------------
' / S A M P L E ... D A T A T A B L E (Products)
' / --------------------------------------------------------------------------------
Function GetDataTable(Optional ByVal Cat As Byte = 0) As DataTable
'// Add Column
Dim DT As New DataTable
With DT
.Columns.Add("ProductPK", GetType(Integer)) '<< Index = 0
.Columns.Add("ProductID", GetType(String)) '<< 1
.Columns.Add("ProductName", GetType(String)) '<< 2
.Columns.Add("UnitPrice", GetType(Double)) '<< 3
.Columns.Add("PictureName", GetType(String)) '<< 4
.Columns.Add("CategoryFK", GetType(Byte)) '<< 5 (เอากลุ่ม/ประเภทสินค้า Foreign Key มาไว้ท้ายสุด เพราะในตารางข้อมูลจริงจะเชื่อมความสัมพันธ์กัน)
End With
'// ... Add rows in the first category. (1 - Coffee)
'/ ProductPK, ProductID, ProductName, UnitPrice, PictureName, CategoryFK
With DT.Rows
.Add(1, "01", "กาแฟร้อน", "50.00", "Coffee.jpg", 1)
.Add(2, "02", "กาแฟเย็น", "60.00", "Coffee4.png", 1)
.Add(3, "03", "คาปูชิโน่", "75.00", "Cappuccino.jpg", 1)
.Add(4, "04", "คาปูชิโน่ - ลาเต้", "80.00", "CappuccinoLatte.jpg", 1)
.Add(5, "05", "เอ็กซ์เพรสโซ่", "90.00", "Expresso.jpg", 1)
End With
'// ... Add rows in category. (2 - Burger)
With DT.Rows
.Add(11, "11", "Classic Chicken", "20.00", "BurgerChicken.png", 2)
.Add(12, "12", "Mexicana", "25.00", "BurgerMexicana.png", 2)
.Add(13, "13", "Lemon Shrimp", "30.00", "BurgerLemonShrimp.png", 2)
.Add(14, "14", "Bacon", "40.00", "BurgerBacon.png", 2)
.Add(15, "15", "Spicy Shrimp", "45.00", "BurgerSpicyShrimp.png", 2)
.Add(16, "16", "Tex Supreme", "50.00", "BurgerTexSupreme.png", 2)
.Add(17, "17", "Fish", "55.00", "BurgerFish.png", 2)
End With
'// ... Add rows in category. (3 - Soft Drink)
With DT.Rows
.Add(21, "21", "Pepsi Can", "20.00", "PepsiCan.png", 3)
.Add(22, "22", "Coke Can", "20.00", "CokeCan.png", 3)
.Add(23, "23", "7Up Can", "20.00", "7upCan.png", 3)
.Add(24, "24", "Pepsi 2 ลิตร", "50.00", "Pepsi2L.jpg", 3)
.Add(25, "25", "Coke 2 ลิตร", "50.00", "Coke2L.jpg", 3)
.Add(26, "26", "น้ำเปล่า", "15.00", "Water.jpg", 3)
End With
'// ... Add rows in category. (4 - Whisky)
With DT.Rows
.Add(41, "41", "วิสกี้ (เพียว)", "100.00", "Whisky.jpg", 4)
.Add(42, "42", "เหล้าขาว (เป๊ก)", "40.00", "Pek.png", 4)
.Add(43, "43", "ม้ากระทืบโรง (เป๊ก)", "50.00", "Horse.jpg", 4)
.Add(44, "44", "เบียร์สิงห์ (กระป๋อง)", "80.00", "SinghaCan.jpg", 4)
.Add(45, "45", "เบียร์ลีโอ (กระป๋อง)", "70.00", "LeoCan.jpg", 4)
.Add(46, "46", "เบียร์ช้าง (กระป๋อง)", "70.00", "ChangCan.jpg", 4)
.Add(47, "47", "Spy Wine Cooler", "50.00", "Spy.jpg", 4)
.Add(48, "48", "โซจู (สตรอเบอรี่)", "90.00", "Soju.jpg", 4)
End With
'// กรองเอาเฉพาะพวกที่แบ่งกลุ่ม/ประเภทสินค้า โดยมีการค้นหาด้วย CategoryFK (หลักสุดท้ายใน DataTable)
If Cat > 0 Then
Dim Result() As DataRow = DT.Select("CategoryFK = " & Cat)
Dim MyDT As New DataTable
If Not Result.Length = 0 Then MyDT = Result.CopyToDataTable
Return MyDT
'// เอาข้อมูลสินค้าทั้งหมด
Else
Return DT
End If
End Function
' / --------------------------------------------------------------------------------
' / ตั้งค่าเริ่มต้นให้กับ DataGridView แบบ Run Time (ใช้โค้ดทั้งหมด)
Private Sub InitializeGrid()
With dgvData
.RowHeadersVisible = False
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.AllowUserToResizeRows = False
.MultiSelect = False
.ReadOnly = False
.RowTemplate.MinimumHeight = 27
.RowTemplate.Height = 27
'/ Columns Specified
'/ Index = 0
.Columns.Add("PK", "Primary Key")
With .Columns("PK")
.ReadOnly = True
.DefaultCellStyle.BackColor = Color.LightGoldenrodYellow
.Visible = False '/ ปกติหลัก Primary Key จะต้องถูกซ่อนไว้
End With
'/ Index = 1
.Columns.Add("ProductID", "Product ID")
.Columns("ProductID").ReadOnly = True
.Columns("ProductID").Visible = False
'/ Index = 2
.Columns.Add("ProductName", "Product Name")
.Columns("ProductName").ReadOnly = True
.Columns("ProductName").DefaultCellStyle.BackColor = Color.LightGoldenrodYellow
'/ Index = 3
.Columns.Add("Quantity", "Quantity")
.Columns("Quantity").ValueType = GetType(Integer)
'/ Index = 4
.Columns.Add("UnitPrice", "Unit Price")
.Columns("UnitPrice").ValueType = GetType(Double)
'/ Index = 5
.Columns.Add("Total", "Total")
.Columns("Total").ValueType = GetType(Double)
.Font = New Font("Tahoma", 11)
'/ Total Column (5)
With .Columns("Total")
.ReadOnly = True
.DefaultCellStyle.BackColor = Color.LightGoldenrodYellow
.DefaultCellStyle.ForeColor = Color.Blue
.DefaultCellStyle.Font = New Font(dgvData.Font, FontStyle.Bold)
End With
'// เพิ่มปุ่มลบ (Index = 6)
Dim btnDelRow As New DataGridViewButtonColumn
dgvData.Columns.Add(btnDelRow)
With btnDelRow
.HeaderText = "Delete F8"
.Text = "Delete"
.UseColumnTextForButtonValue = True
.Width = 30
.ReadOnly = True
.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
.SortMode = DataGridViewColumnSortMode.NotSortable'/ Not sort order but can click header for delete row.
End With
'/ Alignment MiddleRight only columns 3 to 5
For i As Byte = 3 To 5
'/ Header Alignment
.Columns(i).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight
'/ Cell Alignment
.Columns(i).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
Next
'/ Auto size column width of each main by sorting the field.
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
'/ Adjust Header Styles
With .ColumnHeadersDefaultCellStyle
.BackColor = Color.RoyalBlue
.ForeColor = Color.White
.Font = New Font("Tahoma", 11, FontStyle.Bold)
End With
.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
.ColumnHeadersHeight = 36
'/ กำหนดให้ EnableHeadersVisualStyles = False เพื่อให้ยอมรับการเปลี่ยนแปลงสีพื้นหลังของ Header
.EnableHeadersVisualStyles = False
End With
End Sub
' / --------------------------------------------------------------------------------
' / การค้นหาข้อมูลในช่อง TextBox
' / --------------------------------------------------------------------------------
Private Sub txtSearch_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtSearch.KeyPress
'// เมื่อกดคีย์ ENTER เพื่อเริ่มต้นการค้นหาข้อมูล
If e.KeyChar = Chr(13) Then
'/ Replace some word for reserved in DataBase.
txtSearch.Text = txtSearch.Text.Trim.Replace("'", "").Replace("*", "").Replace("%", "")
e.Handled = True '// ปิดเสียง
'/ สร้าง DataTable สมมุติขึ้นมา
Dim DT As DataTable = GetDataTable()
'/ ค้นหาข้อมูลจาก DataTable แล้วรับค่ามาใส่ไว้ใน DataRow
'/ การค้นหาข้อมูลแบบ String จะต้องใส่เครื่องหมาย Single Quote ครอบเอาไว้ เช่น ProductID = '01'
Dim r() As DataRow = DT.Select(" ProductID = " & "'" & txtSearch.Text.Trim & "'")
'// หากพบข้อมูลใน DataTable
If r.Count > 0 Then
'/ ตัวแปรบูลีน Flag แจ้งการค้นหาข้อมูลในตารางกริด (True = พบรายการในแถว, False = ไม่พบ)
Dim blnExist As Boolean = False
'/ ต้องค้นหาข้อมูลจากตารางกริดก่อน เพื่อค้นหาว่ามีรายการสินค้าเดิมหรือไม่?
'/ หากในตารางกริดยังไม่มีแถวรายการ ก็จะข้าม For Loop นี้ไปเพิ่มรายการใหม่ทันที (ครั้งแรกที่ยังไม่มีข้อมูลในตารางกริด)
For iRow As Integer = 0 To dgvData.RowCount - 1
'/ ทดสอบด้วย Primary Key r(0).Item(0) หรือ Product ID r(0).Item(1) ก็ได้
If r(0).Item(0) = dgvData.Rows(iRow).Cells(0).Value Then
'/ เมื่อพบรายการเดิม ก็ให้เพิ่มจำนวนขึ้น 1
dgvData.Rows(iRow).Cells(3).Value += 1
lblLastPrice.Text = "Last Price: " & CDbl(dgvData.Rows(iRow).Cells(4).Value).ToString("0.00")
'/ Flag แจ้งว่าพบข้อมูลเดิมแล้ว
blnExist = True
'/ เมื่อเจอสินค้าเดิมในตารางกริดแล้ว ไม่ว่าจะอยู่แถวลำดับที่เท่าไหร่ ก็ให้ออกจาก For Loop การค้นหาได้เลย
'/ เพราะรายการสินค้าใดๆ จะต้องมีอยู่เพียงแค่รายการเดียว ไม่ต้องเสียเวลาวนรอบกลับไปทำให้จนครบจำนวนแถว
Exit For
End If
Next
'/ กรณีที่พบสินค้าในตารางกริด กำหนด blnExist = True ทำให้ Not True = False จะทำให้ข้ามเงื่อนไขนี้ออกไป
'/ กรณีที่ไม่พบข้อมูลสินค้าเดิมในตารางกริด กำหนด blnExist = False ทำให้ Not False = True เพิ่มรายการสินค้าแถวใหม่เข้าไปในตารางกริดได้
If Not blnExist Then
'/ Primary Key, Product ID, Product Name, Quantity, UnitPrice, Total
dgvData.Rows.Add(r(0).Item(0), r(0).Item(1), r(0).Item(2), "1", Format(CDbl(r(0).Item(3).ToString), "0.00"), "0.00")
lblLastPrice.Text = "Last Price: " & CDbl(r(0).Item(3)).ToString("0.00")
End If
'/ หากไม่ใช้ NOT ก็จะต้องเขียนโปรแกรมแบบนี้
'/ If blnExist = True Then
'/ ไม่ต้องทำอะไร
'/ Else
'/ ทำคำสั่งเพิ่มรายการ
'/ End If
'// คำนวณผลรวมใหม่
Call CalSumTotal()
DT.Dispose()
End If
txtSearch.Clear()
txtSearch.Focus()
End If
End Sub
' / --------------------------------------------------------------------------------
' / Calcualte sum of Total (Column Index = 5)
' / ทำทุกครั้งที่มีการเพิ่มหรือลบแถวรายการ และมีการเปลี่ยนแปลงค่าในเซลล์ Quantity, UnitPrice
Private Sub CalSumTotal()
txtSumTotal.Text = "0.00"
'/ วนรอบตามจำนวนแถวที่มีอยู่ปัจจุบัน
For i As Integer = 0 To dgvData.RowCount - 1
'/ หลักสุดท้ายของตารางกริด = [จำนวน x ราคา]
dgvData.Rows(i).Cells(5).Value = Format(dgvData.Rows(i).Cells(3).Value * dgvData.Rows(i).Cells(4).Value, "#,##0.00")
'/ นำค่าจาก Total มารวมกันเพื่อแสดงผลในสรุปผลรวม (x = x + y)
txtSumTotal.Text = Format(CDbl(txtSumTotal.Text) + CDbl(dgvData.Rows(i).Cells(5).Value), "#,##0.00")
Next
End Sub
' / --------------------------------------------------------------------------------
' / โปรแกรมย่อยในการลบแถวรายการที่เลือกออกไป
Private Sub DeleteRow(ByVal ColName As String)
If dgvData.RowCount = 0 Then Return
'/ ColName เป็นชื่อของหลัก Index = 6 ของตารางกริด (ไปดูที่โปรแกรมย่อย InitializeGrid)
If ColName = "btnDelRow" Then
'// ลบรายการแถวที่เลือกออกไป
dgvData.Rows.Remove(dgvData.CurrentRow)
'/ เมื่อแถวรายการถูกลบออกไป ต้องไปคำนวณหาค่าผลรวมใหม่
Call CalSumTotal()
End If
txtSearch.Focus()
End Sub
' / --------------------------------------------------------------------------------
' / ปุ่มลดจำนวนสินค้าลงทีละ 1 ... แถวของตารางกริดที่ถูกโฟกัส
Private Sub btnDecrement_Click(sender As System.Object, e As System.EventArgs) Handles btnDecrement.Click
If dgvData.RowCount = 0 Then Return
dgvData.Focus()
For iRow As Integer = 0 To dgvData.RowCount - 1
' / หากพบ Primary Key ในหลัก 0 มาตรงกันกับค่าปัจจุบันในแถวของตารางกริด
If dgvData.Rows(iRow).Cells(0).Value = dgvData.CurrentRow.Cells(0).Value Then
If dgvData.Rows(iRow).Cells(3).Value = 0 Then
'/ หรือหากจำนวนมีค่าเป็น 0 ก็ลบแถวออกไปเลย
'dgvData.Rows.Remove(dgvData.CurrentRow)
'dgvData.Refresh()
Exit For
Else
' / ให้ลดจำนวนลง 1 (Quantity = Quantity - 1)
dgvData.Rows(iRow).Cells(3).Value -= 1
Exit For
End If
End If
Next
'// รวมจำนวนเงิน
Call CalSumTotal()
End Sub
' / --------------------------------------------------------------------------------
' / ปุ่มเพิ่มจำนวนสินค้าขึ้นทีละ 1 ... แถวของตารางกริดที่ถูกโฟกัส
Private Sub btnIncrement_Click(sender As System.Object, e As System.EventArgs) Handles btnIncrement.Click
If dgvData.RowCount = 0 Then Return
dgvData.Focus()
For iRow As Integer = 0 To dgvData.RowCount - 1
' / หากพบ Primary Key ในหลัก 0 มาตรงกันกับค่าปัจจุบันในแถวของตารางกริด
If dgvData.Rows(iRow).Cells(0).Value = dgvData.CurrentRow.Cells(0).Value Then
' / ให้เพิ่มจำนวนขึ้น 1 (Quantity = Quantity + 1)
dgvData.Rows(iRow).Cells(3).Value += 1
Exit For
End If
Next
'// รวมจำนวนเงิน
Call CalSumTotal()
End Sub
Private Sub dgvData_CellClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvData.CellClick
Select Case e.ColumnIndex
'// Delete Button
Case 6
'MsgBox(("Row : " + e.RowIndex.ToString & "Col : ") + e.ColumnIndex.ToString)
Call DeleteRow("btnDelRow")
End Select
End Sub
' / --------------------------------------------------------------------------------
' / After you press Enter
Private Sub dgvData_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvData.CellEndEdit
'/ เกิดการเปลี่ยนแปลงค่าในหลัก Index ที่ 3 หรือ 4
Select Case e.ColumnIndex
Case 3, 4 '/ Column Index = 3 (Quantity), Column Index = 4 (UnitPrice)
'/ Quantity
'/ การดัก Error กรณีมีค่า Null Value ให้ใส่ค่า 0 ลงไปแทน
If IsDBNull(dgvData.Rows(e.RowIndex).Cells(3).Value) Then dgvData.Rows(e.RowIndex).Cells(3).Value = "0"
Dim Quantity As Integer = dgvData.Rows(e.RowIndex).Cells(3).Value
'/ UnitPrice
'/ If Null Value
If IsDBNull(dgvData.Rows(e.RowIndex).Cells(4).Value) Then dgvData.Rows(e.RowIndex).Cells(4).Value = "0.00"
Dim UnitPrice As Double = dgvData.Rows(e.RowIndex).Cells(4).Value
dgvData.Rows(e.RowIndex).Cells(4).Value = Format(CDbl(dgvData.Rows(e.RowIndex).Cells(4).Value), "0.00")
'/ Quantity x UnitPrice
dgvData.Rows(e.RowIndex).Cells(5).Value = CDbl((Quantity * UnitPrice).ToString("#,##0.00"))
'/ Calculate Summary
Call CalSumTotal()
End Select
End Sub
' / --------------------------------------------------------------------------------
Private Sub dgvData_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvData.EditingControlShowing
Select Case dgvData.Columns(dgvData.CurrentCell.ColumnIndex).Name
' / Can use both Colume Index or Field Name
Case "Quantity", "UnitPrice"
'/ Stop and Start event handler
RemoveHandler e.Control.KeyPress, AddressOf ValidKeyPress
AddHandler e.Control.KeyPress, AddressOf ValidKeyPress
End Select
End Sub
' / --------------------------------------------------------------------------------
Private Sub ValidKeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
Dim tb As TextBox = sender
Select Case dgvData.CurrentCell.ColumnIndex
Case 3' Quantity is Integer
Select Case e.KeyChar
Case "0" To "9" ' digits 0 - 9 allowed
Case ChrW(Keys.Back) ' backspace allowed for deleting (Delete key automatically overrides)
Case Else ' everything else ....
' True = CPU cancel the KeyPress event
e.Handled = True ' and it's just like you never pressed a key at all
End Select
Case 4' UnitPrice is Double
Select Case e.KeyChar
Case "0" To "9"
' Allowed "."
Case "."
' can present "." only one
If InStr(tb.Text, ".") Then e.Handled = True
Case ChrW(Keys.Back)
'/ Return False is Default value
Case Else
e.Handled = True
End Select
End Select
End Sub
Private Sub frmFoodDrinkMain_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
Me.Dispose()
GC.SuppressFinalize(Me)
Application.Exit()
End Sub
End Class
ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้จากที่นี่ ...
หน้า:
[1]