thongkorn โพสต์ 2017-10-26 16:36:15

[VB.NET] การนำไฟล์ข้อมูลภาพมาแสดงผลในเซลล์ของตารางกริดแบบ Run Time

http://www.g2gnet.com/webboard/images/vbnet/datagridcolumnimage.png
จากโปรเจค แจกฟรีโค้ดโปรแกรมการเก็บบันทึกข้อมูลบุคคล แอดมินจะขอเลือกส่วนสำคัญเพื่อนำมาอธิบายรายละเอียดกันนะครับ สำหรับบทความนี้ คือ การนำไฟล์ข้อมูลภาพมาแสดงผลในเซลล์ของตารางกริดแบบ Run Time ก็เพราะเนื่องจากว่าในฐานข้อมูล MS Access ที่แอดมินออกแบบเอาไว้ จะบันทึกเฉพาะชื่อไฟล์ (PictureName) เอาไว้เท่านั้น ไม่ได้จัดเก็บข้อมูลในรูปแบบ BLOB (Binary Large OBject) ซึ่งจะทำให้ฐานข้อมูลไม่ใหญ่โตเทอะทะ อีกทั้งมีข้อดีที่สำคัญมากคือ สามารถย้ายระบบไปใช้ฐานข้อมูลค่ายอื่นๆได้อย่างไม่ยากเย็นอะไร ...

การที่จะทำเช่นนี้ได้ต้องอาศัยวิธีการที่เราเรียกว่า UnBound Data Control หรือ การไม่ผูกข้อมูลใดๆเข้ากับคอนโทรล เพื่อที่จะสามารถนำชื่อไฟล์ภาพจากตารางข้อมูล ให้ไปปรากฏอยู่ในเซลล์ของตารางกริดได้ (พื้นฐานการนำข้อมูลจาก DataBase มาแสดงผลบนตารางกริด (Data Reader))
http://www.g2gnet.com/webboard/images/vbnet/datagridcolumnimagedb.png
หากไม่มีข้อมูลภาพ เราก็ให้เป็นค่าว่าง (Blank) เอาไว้

โค้ดในส่วนของการนำข้อมูลมาแสดงผล ...
    ' / --------------------------------------------------------------------------------
    ' / Collect all searches and impressions. Come in the same place
    ' / blnSearch = True, Show that the search results.
    ' / blnSearch is set to False, Show all records.
    Private Sub RetrieveData(Optional ByVal blnSearch As Boolean = False)
      strSQL = _
            " SELECT tblContact.ContactPK, tblContact.Fullname, tblContact.Nickname, tblContact.Mobile, " & _
            " tblContact.Phone, tblContact.eMail, tblContact.LineID, tblContact.FacebookID, " & _
            " tblContact.PictureName, tblContact.Note, " & _
            " tblPosition.PositionName, tblDepartment.DepartmentName " & _
            " FROM INNER JOIN (tblDepartment INNER JOIN tblContact ON " & _
            " tblDepartment.DepartmentPK = tblContact.DepartmentFK) ON tblPosition.PositionPK = tblContact.PositionFK "

      '// blnSearch = True for Serach
      If blnSearch Then
            strSQL = strSQL & _
                " WHERE " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " " & " Like '%" & txtSearch.Text & "%'" & _
                " ORDER BY ContactPK "
      Else
            strSQL = strSQL & " ORDER BY ContactPK "
      End If
      '//
      Try
            Cmd = New OleDbCommand
            If Conn.State = ConnectionState.Closed Then Conn.Open()
            Cmd.Connection = Conn
            Cmd.CommandText = strSQL
            Dim DR As OleDbDataReader = Cmd.ExecuteReader
            Dim i As Long = dgvData.RowCount
            While DR.Read
                With dgvData
                  .Rows.Add(i)
                  .Rows(i).Cells(0).Value = DR.Item("ContactPK").ToString
                  .Rows(i).Cells(1).Value = DR.Item("Fullname").ToString
                  .Rows(i).Cells(2).Value = DR.Item("Nickname").ToString
                  .Rows(i).Cells(3).Value = DR.Item("PositionName").ToString
                  .Rows(i).Cells(4).Value = DR.Item("DepartmentName").ToString
                  .Rows(i).Cells(5).Value = DR.Item("Mobile").ToString
                  .Rows(i).Cells(6).Value = DR.Item("Phone").ToString
                  .Rows(i).Cells(7).Value = DR.Item("eMail").ToString
                  .Rows(i).Cells(8).Value = DR.Item("LineID").ToString
                  .Rows(i).Cells(9).Value = DR.Item("FaceBookID").ToString
                  '// Show picture in cell.
                  If DR.Item("PictureName").ToString <> "" Then
                        '//dgvData.Rows(i).Height = 75
                        '// Column 10 = "PictureName"
                        dgvData.Columns(10).Width = 75
                        '// First, before load data into DataGrid and check File exists or not?
                        If Dir(strPathImages & DR.Item("PictureName").ToString) = "" Then
                            '// strPathImages in modDataBase.vb
                            dgvData.Rows(i).Cells(10).Value = Image.FromFile(strPathImages & "people.png")
                        Else
                            dgvData.Rows(i).Cells(10).Value = Image.FromFile(strPathImages & DR.Item("PictureName").ToString)
                        End If
                        '// If image is not exists, then show default image.
                  Else
                        dgvData.Rows(i).Cells(10).Value = Image.FromFile(strPathImages & "people.png")
                        '//dgvData.Rows(i).Height = 75
                        dgvData.Columns(10).Width = 75
                  End If
                  ' / --------------------------------------------------------------------------------
                  '// Keep picture's name into TAG for each cell in DataGrid.
                  '// Used to load images into PictureBox or apply for something else.
                  dgvData.Rows(i).Cells(10).Tag = DR.Item("PictureName").ToString
                  ' / --------------------------------------------------------------------------------
                  '//
                  .Rows(i).Cells(11).Value = DR.Item("Note").ToString
                End With
                i += 1
            End While
            lblRecordCount.Text = ""
            DR.Close()
            '// Adjust row height.
            If chkPicture.Checked Then
                dgvData.Columns("PictureName").Visible = True
                '// Jump to sub program
                Call AdjustRowHeight(75)
            Else
                dgvData.Columns("PictureName").Visible = False
                Call AdjustRowHeight(28)
            End If

      Catch ex As Exception
            MessageBox.Show(ex.Message)
      End Try
      '//
      txtSearch.Clear()
    End Sub
ต้องทำการตรวจสอบก่อนว่ามีชื่อไฟล์ภาพอยู่หรือไม่ หากไม่มีให้โหลดภาพอื่น (people.png) ลงไปแทน ไม่อย่างนั้นมันก็จะเกิดเอ้อเหรอซิครับ
    '// First, before load data into DataGrid and check File exists or not?
    If Dir(strPathImages & DR.Item("PictureName").ToString) = "" Then
      '// strPathImages in modDataBase.vb
      dgvData.Rows(i).Cells(10).Value = Image.FromFile(strPathImages & "people.png")
    Else
      dgvData.Rows(i).Cells(10).Value = Image.FromFile(strPathImages & DR.Item("PictureName").ToString)
    End Ifเพราะเนื่องจากหลักที่ 10 (เป็นค่า Index นะครับ) เรากำหนดให้เป็น Dim colPicture As New DataGridViewImageColumn มันถึงจะแสดงผลภาพออกมา ... แล้วถ้าหากว่าต้องการอยากรู้ชื่อไฟล์ภาพแต่ละภาพจะทำอย่างไร???
จะมีอยู่บรรทัดคำสั่งหนึ่ง คือการโหลดชื่อไฟล์ภาพเข้าสู่คุณสมบัติ TAG ในเซลล์ของตารางกริด คือ ...
    ' / --------------------------------------------------------------------------------
    '// Keep picture's name into TAG for each cell in DataGrid.
    '// Used to load images into PictureBox or apply for something else.
   dgvData.Rows(i).Cells(10).Tag = DR.Item("PictureName").ToString
   ' / --------------------------------------------------------------------------------นั่นก็หมายความว่า หากเราต้องการนำชื่อไฟล์ภาพไปใช้งานก็กำหนดที่นี่แหละครับ ทำให้เราประหยัดตัวแปร หรือไม่ต้องเพิ่มหลักของตารางกริดเพื่อเอาข้อมูลมาซ่อน ... นี่ก็เป็นอีกหนึ่งเคล็ดลับเทคนิคของการใช้งานตารางกริด

การหาค่า Primary Key และเรียกใช้ชื่อไฟล์ภาพ ... จะอยู่ในเหตุการณ์ของการดับเบิ้ลคลิ๊กเมาส์ในแต่ละแถวของตารางกริด
http://www.g2gnet.com/webboard/images/vbnet/datagridcolumnimagepk.png
    ' / -----------------------------------------------------------------------------
    ' / Double Click mouse on DataGridView.
    ' / -----------------------------------------------------------------------------
    Private Sub dgvData_DoubleClick(sender As Object, e As System.EventArgs) Handles dgvData.DoubleClick
      If dgvData.RowCount <= 0 Then Return
      '// Read the value of the focus row.
      Dim iRow As Integer = dgvData.CurrentRow.Index
      '// Get Primary Key in Column(0) and show picture's name which It is stored in TAG property each cell.
      MessageBox.Show("Primary Key is : " & dgvData.Item(0, iRow).Value & vbCrLf & _
                        "Picture Name: " & dgvData.Item(10, iRow).Tag)
    End Sub
กรณีที่เราต้องการให้แสดงหรือไม่แสดงผลรูปภาพ ...
    ' / -----------------------------------------------------------------------------
    ' / Show picture or not?
    ' / -----------------------------------------------------------------------------
    Private Sub chkPicture_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles chkPicture.CheckedChanged
      If chkPicture.Checked Then
            dgvData.Columns("PictureName").Visible = True
            Call AdjustRowHeight(75)
      Else
            dgvData.Columns("PictureName").Visible = False
            Call AdjustRowHeight(28)
      End If
    End Sub

    ' / -----------------------------------------------------------------------------
    ' / Change the height of the rows.
    ' / -----------------------------------------------------------------------------
    Private Sub AdjustRowHeight(h As Integer)
      For i As Integer = 0 To dgvData.Rows.Count - 1
            dgvData.Rows(i).Height = h
      Next
    End Subมันจำเป็นจะต้องมีการปรับขนาดความสูงของแถวแบบ @Run Time ตามโค้ดด้านบน ในกรณีที่ปิดเปิดการแสดงผลภาพ

แถมท้าย ... การออกแบบตารางกริด แอดมินชอบการใช้โค้ดสั่งให้ทำงานในขณะ Run Time (โปรแกรมทำงานจึงจะเห็นผล) มากกว่า Design Time (ปรับแต่งคุณสมบัติต่างๆก่อนทำการสั่งรัน) ก็เพราะมีหลายๆเหตุผล หลักๆก็คือหากเราต้องการเพิ่มฟิลด์ (Field ไม่ได้อ่านว่า ฟิว) หรือตัดออกในภายหลัง สามารถทำได้ง่ายและรวดเร็วกว่า หรือการโยกย้ายไปใช้ Control ของค่ายอื่นๆแทนก็ง่ายดาย ดังนั้นแอดมินขอแนะนำให้เขียนโค้ดทำเป็นเทมเพลตเอาไว้รอล่วงหน้าเลยครับ
    ' / --------------------------------------------------------------------------------
    '// Initialize DataGridView @Run Time
    Private Sub SetupDGVData()
      With dgvData
            .RowHeadersVisible = False
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .AllowUserToResizeRows = False
            .MultiSelect = False
            .SelectionMode = DataGridViewSelectionMode.FullRowSelect
            .ReadOnly = True
            .Font = New Font("Tahoma", 9)
            ' Columns Specified
            .Columns.Add("ContactPK", "ContactPK")
            .Columns.Add("Fullname", "Full name")
            .Columns.Add("Nickname", "Nickname")
            .Columns.Add("PositionName", "Position")
            .Columns.Add("DepartmentName", "Department")
            .Columns.Add("Mobile", "Mobile")
            .Columns.Add("Phone", "Phone Ext.")
            .Columns.Add("Email", "Email")
            .Columns.Add("LineID", "Line")
            .Columns.Add("FacebookID", "Facebook")
            '// Column Picture
            Dim colPicture As New DataGridViewImageColumn
            .Columns.Add(colPicture)
            With colPicture
                .HeaderText = "Picture"
                .Name = "PictureName"
                .ImageLayout = DataGridViewImageCellLayout.Stretch
            End With
            '//
            .Columns.Add("Note", "Note")
            '// Hidden Columns
            .Columns(0).Visible = False
            .Columns(7).Visible = False
            .Columns(8).Visible = False
            .Columns(9).Visible = False
            '// PictureName
            .Columns("PictureName").Visible = True
            .Columns("Note").Visible = False
            ' Autosize Column
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            '// Even-Odd Color
            .AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
            ' Adjust Header Styles
            With .ColumnHeadersDefaultCellStyle
                .BackColor = Color.Navy
                .ForeColor = Color.Black ' Color.White
                .Font = New Font("Tahoma", 9, FontStyle.Bold)
            End With
      End With
    End Subสำหรับตอนนี้ก็ขอจบแต่เพียงเท่านี้ ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่

g2gsoftuser โพสต์ 2022-10-25 19:52:00

ขอบคุณครับ
หน้า: [1]
ดูในรูปแบบกติ: [VB.NET] การนำไฟล์ข้อมูลภาพมาแสดงผลในเซลล์ของตารางกริดแบบ Run Time