|  | 
 
|  จากตอนที่แล้วแอดมินได้นำเสนอ การนำเอา ComboBox Control ไปใส่ไว้ในตารางกริด MSFlexGrid สำหรับ Visual Basic 6 ในตอนนี้ก็จะขยับมาใช้ VB.NET โดยแบ่งวิธีคิดออกเป็น 3 วิธี ซึ่งแต่ละวิธีจะมีทั้งความเหมือนและความแตกต่างผสมกันไป แอดมินอยากให้ลองศึกษาและสังเกตกันให้ดีๆ เพราะสิ่งที่แอดมินนำมาเล่าสู่กันฟังนี้มันเป็นพื้นฐาน ที่จะนำทางไปสู่การแก้ปัญหาในการเขียนโปรแกรมในลำดับต่อไป ...
 
 3 วิธีคิด แบ่งออกได้ดังต่อไปนี้
 - คิดแบบ VB6
 - คิดแบบ VB6 แต่ใช้ความสามารถของ VB.NET ในการสร้าง ComboBox แบบ @Run Time
 - คิดแบบ Visual Basic .NET ฉบับเต็ม
 
 สำหรับวิธีแรก คงไม่ต้องอธิบายอะไรมากมายนัก ก็คือนำเอา ComboBox มาแปะลงบนฟอร์มก่อน จากนั้นก็อาศัยหลักการเลื่อนตำแหน่ง ComboBox ไปปิดทับในแต่ละเซลล์ที่ต้องการ (ใช้หลักที่ 3 หรือ Index = 2 ตามเดิม)
 โค้ดวิธีการแรก
 
 คัดลอกไปที่คลิปบอร์ดPublic Class frmDGVCBV1
    Private Sub frmDGVCBV1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        '//
        With DataGridView1
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .SelectionMode = DataGridViewSelectionMode.CellSelect
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            .MultiSelect = False
            .ColumnCount = 3
            .Columns(0).Name = "Column 1"
            .Columns(1).Name = "Column 2"
            .Columns(2).Name = "Column 3"
            '// ป้องกันการเข้าไปแก้ไขในเซลล์โดยตรง
            .Columns(2).ReadOnly = True
        End With
        Dim row As String() = New String() {"1", "Product 1", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"2", "Product 2", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"3", "Product 3", "M150"}
        DataGridView1.Rows.Add(row)
        row = New String() {"4", "Product 4", "M16"}
        DataGridView1.Rows.Add(row)
        '//
        With ComboBox1
            .DropDownStyle = 2
            '// Load the ComboBox's list.
            .Items.Add("M100")
            .Items.Add("M150")
            .Items.Add("M16")
            ' Hidden Control
            .Visible = False
        End With
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / เกิดเหตุการณ์การคลิ๊กเซลล์ แถวใดๆแต่เป็นหลักที่ 3 (Index = 2)
    Private Sub DataGridView1_CellClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
        If e.RowIndex < 0 Then Exit Sub
        Select Case e.ColumnIndex
            '// เราไม่ต้องการหลัก 0 กับหลัก 1 ดังนั้นต้องปิดการแสดงผลของ ComboBox เอาไว้
            Case 0 To 1 : ComboBox1.Visible = False
                '// โฟกัสมาที่หลักที่ 3 (Index = 2) ที่เราต้องการเท่านั้น
            Case 2
                '// เปิดให้มองเห็น ComboBox
                ComboBox1.Visible = True
                '// เพิ่ม ComboBox เข้ามาในตารางกริด
                DataGridView1.Controls.Add(ComboBox1)
                '// นำค่าจาก DataGrid มาเทียบค่าใน ComboBox เพื่อให้แสดงผลค่าที่เท่ากัน
                ComboBox1.Text = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
                '// พื้นที่แสดงผลในเซลล์.
                Dim oRectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                ' หาค่าระยะ X, Y เพื่อกำหนดพิกัด (Coordinate) ให้กับ ComboBox
                ComboBox1.Size = New Size(oRectangle.Width, oRectangle.Height)
                '// กำหนดตำแหน่งของ ComboBox ไปทับเซลล์
                ComboBox1.Location = New Point(oRectangle.X, oRectangle.Y)
        End Select
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / หากเกิดการเลือกค่าใน ComboBox ก็ให้คัดลอกค่านี้ไปยังเซลล์ใน DataGridView
    Private Sub ComboBox1_TextChanged(sender As Object, e As System.EventArgs) Handles ComboBox1.TextChanged
        '// นำค่าจาก ComboBox ไปใส่ไว้ในเซลล์ของ DataGridView
        DataGridView1.CurrentCell.Value = ComboBox1.Text
    End Sub
    Private Sub frmDGVCBV1_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize
        ComboBox1.Visible = False
    End Sub
    Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        '// นำค่าจาก ComboBox ไปใส่ไว้ในเซลล์ของ DataGridView
        DataGridView1.CurrentCell.Value = ComboBox1.Text
    End Sub
    Private Sub frmDGVCBV1_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        Me.Dispose()
    End Sub
End Class
วิธีการที่สอง ก็จะใช้เหมือนวิธีการแรก แต่เปลี่ยนใหม่โดยให้สร้าง ComboBox Control ขึ้นมาในขณะ @Run Time แทน
 
 ประกาศตัวแปร ComboBoxคัดลอกไปที่คลิปบอร์ด'// ประกาศตัวแปร Object ของ ComboBox
    Dim cb As New ComboBox
 ให้สังเกตดูว่าในหลักที่ 3 (Index = 2) แอดมินยังกำหนดช่องเซลล์ DataGridViewTextBoxColumn คือยังคงเป็นแบบ TextBox ตามเดิมคัดลอกไปที่คลิปบอร์ด        '// 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 = "Column 1"
            .Columns(1).Name = "Column 2"
            .Columns(2).Name = "Column 3"
            '// ป้องกันการเข้าไปแก้ไขในเซลล์โดยตรง
            .Columns(2).ReadOnly = True
        End With
        '//
        With cb
            .DropDownStyle = 2
            '// Load the ComboBox's list.
            .Items.Add("M100")
            .Items.Add("M150")
            .Items.Add("M16")
            '// Hidden Control
            .Visible = False
        End With
 
 นอกเหนือไปจากการคำนวณหาตำแหน่งที่ ComboBox จะต้องเคลื่อนย้ายไปปิดทับเซลล์แล้ว เราจะต้องสร้างเหตุการณ์ (Event) เมื่อเกิดการเลือกค่าไอเทมใน ComboBox เพิ่มขึ้นมาอีก (AddHandler cb.TextChanged, AddressOf cb_TextChanged) ในส่วนนี้เองที่ VB.NET ได้เพิ่มขีดความสามารถขึ้นมาสูงกว่า VB6คัดลอกไปที่คลิปบอร์ด    ' / -------------------------------------------------------------------------------------
    ' / เกิดเหตุการณ์การคลิ๊กเซลล์ แถวใดๆแต่เป็นหลักที่ 3 (Index = 2)
    Private Sub DataGridView1_CellClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
        If e.RowIndex < 0 Then Exit Sub
        Select Case e.ColumnIndex
            '// เราไม่ต้องการหลัก 0 กับหลัก 1 ดังนั้นต้องปิดการแสดงผลของ ComboBox เอาไว้
            Case 0 To 1 : cb.Visible = False
                '// โฟกัสมาที่หลักที่ 3 (Index = 2) ที่เราต้องการเท่านั้น
            Case 2
                '// เปิดให้มองเห็น ComboBox
                cb.Visible = True
                '// Adding ComboBox control into DataGridView   
                DataGridView1.Controls.Add(cb)
                '// นำค่าจาก DataGrid มาเทียบค่าใน ComboBox เพื่อให้แสดงผลค่าที่เท่ากัน
                cb.Text = DataGridView1.CurrentCell.Value
                '// พื้นที่แสดงผลในเซลล์.  
                Dim oRectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                ' หาค่าระยะ X, Y เพื่อกำหนดพิกัด (Coordinate) ให้กับ ComboBox
                cb.Size = New Size(oRectangle.Width, oRectangle.Height)
                '// Setting Location
                cb.Location = New Point(oRectangle.X, oRectangle.Y)
                '// การสร้างเหตุการณ์ (Event) เมื่อเกิดการเลือกไอเทมใน ComboBox ก็จะส่งผลให้กับเซลล์ในตารางกริด
                AddHandler cb.TextChanged, AddressOf cb_TextChanged
        End Select
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / หากเกิดการเลือกค่าใน ComboBox ก็ให้คัดลอกค่านี้ไปยังเซลล์ใน DataGridView
    Private Sub cb_TextChanged(sender As Object, e As System.EventArgs)
        cb.Visible = False
        '// นำค่าจาก ComboBox ไปใส่ไว้ในเซลล์ของ DataGridView
        If DataGridView1.CurrentCell.ColumnIndex = 2 AndAlso cb.Text <> "" Then DataGridView1.CurrentCell.Value = cb.Text
    End Sub
 โค้ดวิธีการที่สอง
 
 คัดลอกไปที่คลิปบอร์ดPublic Class frmDGVCBV2
    '// ประกาศตัวแปร Object ของ ComboBox
    Dim cb As New ComboBox
    Private Sub frmDGVCBV2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        '//
        With DataGridView1
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .SelectionMode = DataGridViewSelectionMode.CellSelect
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            .MultiSelect = False
        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 = "Column 1"
            .Columns(1).Name = "Column 2"
            .Columns(2).Name = "Column 3"
            '// ป้องกันการเข้าไปแก้ไขในเซลล์โดยตรง
            .Columns(2).ReadOnly = True
        End With
        '//
        With cb
            .DropDownStyle = 2
            '// Load the ComboBox's list.
            .Items.Add("M100")
            .Items.Add("M150")
            .Items.Add("M16")
            '// Hidden Control
            .Visible = False
        End With
        '//
        Dim row As String() = New String() {"1", "Product 1", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"2", "Product 2", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"3", "Product 3", "M150"}
        DataGridView1.Rows.Add(row)
        row = New String() {"4", "Product 4", "M16"}
        DataGridView1.Rows.Add(row)
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / เกิดเหตุการณ์การคลิ๊กเซลล์ แถวใดๆแต่เป็นหลักที่ 3 (Index = 2)
    Private Sub DataGridView1_CellClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellClick
        If e.RowIndex < 0 Then Exit Sub
        Select Case e.ColumnIndex
            '// เราไม่ต้องการหลัก 0 กับหลัก 1 ดังนั้นต้องปิดการแสดงผลของ ComboBox เอาไว้
            Case 0 To 1 : cb.Visible = False
                '// โฟกัสมาที่หลักที่ 3 (Index = 2) ที่เราต้องการเท่านั้น
            Case 2
                '// เปิดให้มองเห็น ComboBox
                cb.Visible = True
                '// Adding ComboBox control into DataGridView   
                DataGridView1.Controls.Add(cb)
                '// นำค่าจาก DataGrid มาเทียบค่าใน ComboBox เพื่อให้แสดงผลค่าที่เท่ากัน
                cb.Text = DataGridView1.CurrentCell.Value
                '// พื้นที่แสดงผลในเซลล์.  
                Dim oRectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True)
                ' หาค่าระยะ X, Y เพื่อกำหนดพิกัด (Coordinate) ให้กับ ComboBox
                cb.Size = New Size(oRectangle.Width, oRectangle.Height)
                '// Setting Location
                cb.Location = New Point(oRectangle.X, oRectangle.Y)
                '// การสร้างเหตุการณ์ (Event) เมื่อเกิดการเลือกไอเทมใน ComboBox ก็จะส่งผลให้กับเซลล์ในตารางกริด
                AddHandler cb.TextChanged, AddressOf cb_TextChanged
        End Select
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / หากเกิดการเลือกค่าใน ComboBox ก็ให้คัดลอกค่านี้ไปยังเซลล์ใน DataGridView
    Private Sub cb_TextChanged(sender As Object, e As System.EventArgs)
        cb.Visible = False
        '// นำค่าจาก ComboBox ไปใส่ไว้ในเซลล์ของ DataGridView
        If DataGridView1.CurrentCell.ColumnIndex = 2 AndAlso cb.Text <> "" Then DataGridView1.CurrentCell.Value = cb.Text
    End Sub
    ' / -------------------------------------------------------------------------------------
    ' / หากเกิดการเลือกค่าใน ComboBox ก็ให้คัดลอกค่านี้ไปยังเซลล์ใน DataGridView
    Private Sub DataGridView1_CellLeave(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellLeave
        cb.Visible = False
        If DataGridView1.CurrentCell.ColumnIndex = 2 AndAlso cb.Text <> "" Then DataGridView1.CurrentCell.Value = cb.Text
    End Sub
    Private Sub frmDGVCBV2_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize
        cb.Visible = False
    End Sub
    Private Sub frmDGVCBV2_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        Me.Dispose()
    End Sub
End Class
สำหรับวิธีการที่สาม เราๆท่านๆก็คงจะพบเห็นข้อมูลได้ทั่วๆไปตามเว็บไซต์ต่างๆนั่นเอง โดยอาศัยขีดความสามารถที่มีอยู่ในตัวของ VB.NET ในการเพิ่ม Control ในตัวของ DataGridView ...
 
 ก็เพราะ DataGridView มันมีกลวิธี (Method) ในการนำเอา ComboBox มาใส่ไว้ในเซลล์ของตัวมันเองได้นั่นเองคัดลอกไปที่คลิปบอร์ด        '// เพิ่ม ComboBox
        Dim cmb As New DataGridViewComboBoxColumn()
        With cmb
            .HeaderText = "ComboBox"
            .Items.Add("M100")
            .Items.Add("M150")
            .Items.Add("M16")
        End With
        DataGridView1.Columns.Add(cmb)
โค้ดวิธีการที่สาม
 
 คัดลอกไปที่คลิปบอร์ดPublic Class frmDGVCBV3
    Private Sub frmDGVCBV3_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        '//
        With DataGridView1
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .SelectionMode = DataGridViewSelectionMode.CellSelect
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            .MultiSelect = False
        End With
        '// Declare columns type.
        Dim Column1 As New DataGridViewTextBoxColumn()
        Dim Column2 As New DataGridViewTextBoxColumn()
        '// Add new Columns
        DataGridView1.Columns.AddRange(New DataGridViewColumn() { _
                Column1, Column2 _
                })
        With DataGridView1
            .Columns(0).Name = "Column 1"
            .Columns(1).Name = "Column 2"
        End With
        '// เพิ่ม ComboBox
        Dim cmb As New DataGridViewComboBoxColumn()
        With cmb
            .HeaderText = "ComboBox"
            .Items.Add("M100")
            .Items.Add("M150")
            .Items.Add("M16")
        End With
        DataGridView1.Columns.Add(cmb)
        '//
        Dim row As String() = New String() {"1", "Product 1", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"2", "Product 2", "M100"}
        DataGridView1.Rows.Add(row)
        row = New String() {"3", "Product 3", "M150"}
        DataGridView1.Rows.Add(row)
        row = New String() {"4", "Product 4", "M16"}
        DataGridView1.Rows.Add(row)
        '//
    End Sub
    Private Sub frmDGVCBV3_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        Me.Dispose()
    End Sub
End Class
Conclusion: หลายๆคนอาจจะงงและสงสัยว่า ทำไมแอดมินต้องมาใช้วิธีการอะไรให้ยุ่งยาก ก็เล่นแบบวิธีการที่ 3 ไปเลยซ่ะก็สิ้นเรื่อง ... ลองคิดเล่นๆดูก่อนว่าหากเราต้องการเพิ่ม DateTimePicker (หรือ Control ตัวอื่นๆ) เข้าไปในเซลล์ของตารางกริดแทน ComboBox ท่านจะทำอย่างไร???
 ดาวนโหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่
 
 
 | 
 
xขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึงคุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน  |