|
การสร้างหน้าจอ 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) ได้จากที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|