thongkorn โพสต์ 2019-3-17 14:01:41

[VB.NET] การสร้าง NumericUpDown หรือปุ่มเพิ่มลดค่ามาใส่ไว้ในตารางกริดแบบไดนามิค

http://www.g2gnet.com/webboard/images/vbnet/numericupdown.png

บทความนี้เป็นการขยายขีดความสามารถของตารางกริด (DataGridView) ซึ่งเป็น Control (หรือ Component) พื้นฐานที่ติดมาจากไมโครซอฟท์ ก็จะคล้ายๆกับ การนำเอา DateTimePicker และปุ่มคำสั่ง Button มาแสดงผลในตารางกริด นัั่นเอง แต่ครั้งนี้จะเป็น การนำเอาปุ่มที่เพิ่มหรือลดค่าตัวเลขแบบจำนวนเต็ม (NumericUpDown) มาใส่เข้าไปตารางกริดแทน (กำหนดค่า 1 - 100) แต่ทว่าจะมีอะไรพิเศษที่แตกต่างไปจากของเดิมเล็กน้อย เพราะจะเกิด 2 เหตุการณ์คือ การนำเมาส์ไปคลิ๊กที่เซลล์ของตารางกริดที่เราต้องการ จากนั้นตัว NumericUpDown ก็จะปรากฏขึ้นมา และการกดคีย์จากแป้นพิมพ์ลงไปในเซลล์ของตารางกริดแทน เพื่อป้องกันการกดค่าคีย์ที่เราไม่ต้องการ นอกจากตัวเลข 0 ถึง 9 เท่านั้น ...

เหตุการณ์ในการนำเมาส์ไปคลิ๊กที่เซลล์ของตารางกริด จะบังคับให้ตัว NumericUpDown ขึ้นมาแสดงผลทับลงไปในเซลล์แทน (โฟกัสไปในหลักที่ 3 หรือ Index = 2) ...
    '// If users click cell (index = 2).
    Private Sub DataGridView1_CellClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
      Select Case e.ColumnIndex
            '// NumericUpDown
            Case 2
                '//Adding NumericUpDown control into DataGridView   
                DataGridView1.Controls.Add(nUpDown)

                '// It returns the retangular area that represents the Display area for a cell
                Dim oRectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)

                '//Setting area for NumericUpDown Control
                nUpDown.Size = New Size(oRectangle.Width, oRectangle.Height)

                '// Setting Location
                nUpDown.Location = New Point(oRectangle.X, oRectangle.Y)
                '// Read value from DataGridView into NumericUpDown
                nUpDown.Value = DataGridView1.CurrentCell.Value
                '// Now make it visible
                nUpDown.Visible = True
                '// Force to change date value at nUpDown_ValueChanged Event.
                AddHandler nUpDown.ValueChanged, AddressOf nUpDown_ValueChanged

                '// Delete Button
            Case 3
                'MsgBox(("Row : " + e.RowIndex.ToString & "Col : ") + e.ColumnIndex.ToString)
                Dim colName As String = DataGridView1.Columns(e.ColumnIndex).Name
                If colName = "btnDelRow" Then
                  '// Delete current row from DataGridView1
                  DataGridView1.Rows.Remove(DataGridView1.CurrentRow)
                End If
      End Select
    End Sub
เหตุการณ์ที่เกิดการกดคีย์จากแป้นพิมพ์ ทำให้เราโฟกัสการป้อนค่าในเซลล์นั้นๆ แล้วทำการเช็คค่าคีย์ที่กดลงไป ...
    ' / --------------------------------------------------------------------------------
    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
      Select Case DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Index
            '// ColumeIndex 2 is an integer value.
            Case 2
                '// Force to validate value at ValidKeyPress Event.
                RemoveHandler e.Control.KeyPress, AddressOf ValidKeyPress
                AddHandler e.Control.KeyPress, AddressOf ValidKeyPress
      End Select
    End Sub
โปรแกรมย่อยตรวจสอบการกดแป้นพิมพ์ โดยรับค่าได้เฉพาะตัวเลข 0 - 9 และ Backspace เท่านั้น ...
    ' / --------------------------------------------------------------------------------
    Private Sub ValidKeyPress(sender As System.Object, e As System.Windows.Forms.KeyPressEventArgs)
      Select Case DataGridView1.CurrentCell.ColumnIndex
            Case 2'// 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
      End Select
    End Sub
มาดูโค้ดรวมทั้งหมดกันเถอะ ...
#Region "ABOUT"
' / --------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
' / Facebook: https://www.facebook.com/commonindy (Worldwide)
' / More: http://www.g2gnet.com/webboard
' / Purpose: Adding NumericUpDown and Button control into DataGridView @Runtime.
' / Microsoft Visual Basic .NET (2010)
' /
' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
' / You can modify and/or distribute without to inform the developer.
' / --------------------------------------------------------------------------------
#End Region

Public Class frmDataGridUpDown
    '// Declare variable object of NumericUpDown
    Dim nUpDown As New NumericUpDown
    Dim LastValue As Integer

    Private Sub frmDataGridUpDown_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
      '// Initialize DataGridView Control
      With DataGridView1
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            .RowTemplate.Height = 40
      End With
      '// Declare columns type.
      Dim Column1 As New DataGridViewTextBoxColumn()
      Dim Column2 As New DataGridViewTextBoxColumn()
      Dim Column3 As New DataGridViewTextBoxColumn()
      '// Add new Columns
      DataGridView1.Columns.AddRange(New DataGridViewColumn() { _
                Column1, Column2, Column3 _
                })
      With DataGridView1
            .Columns(0).Name = "Product ID"
            .Columns(1).Name = "Product Name"
            .Columns(2).Name = "NumericUpDown"
      End With
      '// Add 4th column (Index = 3), It's Button.
      Dim btn As New DataGridViewButtonColumn()
      DataGridView1.Columns.Add(btn)
      With btn
            .HeaderText = ""
            .Text = "Delete"
            .Name = "btnDelRow"
            .UseColumnTextForButtonValue = True
            .Width = 120
      End With
      ' Adjust Header Styles
      With DataGridView1.ColumnHeadersDefaultCellStyle
            .BackColor = Color.Navy
            .ForeColor = Color.Black
            .Font = New Font("Century Gothic", 18, FontStyle.Bold)
            .WrapMode = DataGridViewTriState.False
      End With
      With DataGridView1
            .Font = New Font("Century Gothic", 20)
      End With

      '// SAMPLE DATA
      Dim RandomClass As New Random()
      '// DateTime.Today.AddDays(-RandomClass.Next(365)) --> Random past date 365 days.
      Dim row As String() = New String() { _
            "1", "Product 1", RandomClass.Next(99)}
      DataGridView1.Rows.Add(row)
      row = New String() { _
            "2", "Product 2", RandomClass.Next(99)}
      DataGridView1.Rows.Add(row)
      row = New String() { _
            "3", "Product 3", RandomClass.Next(99)}
      DataGridView1.Rows.Add(row)
      row = New String() { _
            "4", "Product 4", RandomClass.Next(99)}
      '// Add new row.
      DataGridView1.Rows.Add(row)
      '// Initialize NumericUpDown @Run Time
      With nUpDown
            .DecimalPlaces = 0
            .Increment = 1
            .Maximum = 100
            .Minimum = 1
            .ReadOnly = True
      End With
    End Sub

    '// If users click cell (index = 2).
    Private Sub DataGridView1_CellClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
      Select Case e.ColumnIndex
            '// NumericUpDown
            Case 2
                '//Adding NumericUpDown control into DataGridView   
                DataGridView1.Controls.Add(nUpDown)

                '// It returns the retangular area that represents the Display area for a cell
                Dim oRectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)

                '//Setting area for NumericUpDown Control
                nUpDown.Size = New Size(oRectangle.Width, oRectangle.Height)

                '// Setting Location
                nUpDown.Location = New Point(oRectangle.X, oRectangle.Y)
                '// Read value from DataGridView into NumericUpDown
                nUpDown.Value = DataGridView1.CurrentCell.Value
                '// Now make it visible
                nUpDown.Visible = True
                '// Force to change date value at nUpDown_ValueChanged Event.
                AddHandler nUpDown.ValueChanged, AddressOf nUpDown_ValueChanged

                '// Delete Button
            Case 3
                'MsgBox(("Row : " + e.RowIndex.ToString & "Col : ") + e.ColumnIndex.ToString)
                Dim colName As String = DataGridView1.Columns(e.ColumnIndex).Name
                If colName = "btnDelRow" Then
                  '// Delete current row from DataGridView1
                  DataGridView1.Rows.Remove(DataGridView1.CurrentRow)
                End If
      End Select
    End Sub

    '// Event Handler when the change value in NumericUpDown.
    Private Sub nUpDown_ValueChanged(sender As Object, e As System.EventArgs)
      '// Display numeric value.
      DataGridView1.CurrentCell.Value = Val(nUpDown.Value)
    End Sub

    '// Event when the change value in Current Cell.
    Private Sub DataGridView1_CellEndEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
      Select Case e.ColumnIndex
            Case 2
                If Val(DataGridView1.CurrentCell.Value.ToString) > 100 Then
                  DataGridView1.CurrentCell.Value = LastValue
                ElseIf Val(DataGridView1.CurrentCell.Value.ToString) <= 0 Then
                  DataGridView1.CurrentCell.Value = LastValue
                Else
                  DataGridView1.CurrentCell.Value = Val(DataGridView1.CurrentCell.Value)
                End If
      End Select
    End Sub

    Private Sub DataGridView1_CellEnter(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
      Select Case e.ColumnIndex
            Case 2
                '// Keep last value before edit.
                LastValue = Val(DataGridView1.CurrentCell.Value)
      End Select
    End Sub

    Private Sub DataGridView1_CellLeave(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellLeave
      '// Hidden Value
      nUpDown.Visible = False
    End Sub

    Private Sub frmDataGridUpDown_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize
      nUpDown.Visible = False
    End Sub

    ' / --------------------------------------------------------------------------------
    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
      Select Case DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Index
            '// ColumeIndex 2 is an integer value.
            Case 2
                '// Force to validate value at ValidKeyPress Event.
                RemoveHandler e.Control.KeyPress, AddressOf ValidKeyPress
                AddHandler e.Control.KeyPress, AddressOf ValidKeyPress
      End Select
    End Sub

    ' / --------------------------------------------------------------------------------
    Private Sub ValidKeyPress(sender As System.Object, e As System.Windows.Forms.KeyPressEventArgs)
      Select Case DataGridView1.CurrentCell.ColumnIndex
            Case 2'// 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
      End Select
    End Sub
End Class
ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่ ...

downrung โพสต์ 2019-3-17 20:24:34

คล้ายๆ จะตอบโจทย์ผมได้เลยครับ

thongkorn โพสต์ 2019-3-18 12:11:32

downrung ตอบกลับเมื่อ 2019-3-17 20:24
คล้ายๆ จะตอบโจทย์ผมได้เลยครับ

ขอบคุณที่ใช้บริการครับผม 5555+
หน้า: [1]
ดูในรูปแบบกติ: [VB.NET] การสร้าง NumericUpDown หรือปุ่มเพิ่มลดค่ามาใส่ไว้ในตารางกริดแบบไดนามิค