Access
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Access

Kiểm soát ListView Xử lý sự kiện kéo thả

Giới thiệu.

Chúng ta đã quen thuộc với các thao tác Kéo và Thả trên Điều khiển TreeView, trong Ms-Access sắp xếp lại các nút. Tất cả các bản ghi cơ sở cho các nút điều khiển Treeview đến từ một Bảng truy cập duy nhất. Chúng tôi luôn cập nhật ParentID của Nút nguồn giá trị trường, với Giá trị ID của nút đích trên cùng một bản ghi Bảng, để thực hiện thay đổi vị trí trên Điều khiển TreeView. Các bản ghi không được di chuyển thực tế ở bất cứ đâu.

Ở đây, với việc bổ sung Điều khiển ListView cùng với Điều khiển TreeView, chúng tôi dự định làm việc với hai Bảng truy cập khác nhau.

  1. lvCategory - Mã và Mô tả Danh mục.
  2. lvProducts - Sản phẩm theo danh mục.

Bằng cách này, dễ hiểu hơn về mối quan hệ giữa cả hai Bảng. Chúng tôi phải thực hiện những thay đổi nào và ở đâu, khi một Mục sản phẩm (mục ListView) chuyển từ Danh mục này sang Danh mục khác trên Điều khiển TreeView.

lvCategory Bảng Access có 20 bản ghi cho các nút TreeView và Sản phẩm lv Bảng có 45 cho Điều khiển ListView. Một hoặc nhiều bản ghi trong bảng Sản phẩm liên quan trực tiếp đến danh mục sản phẩm trên Bảng danh mục. Mối quan hệ giữa chúng đã được cập nhật với giá trị Trường ID danh mục (CID) trên ParentID của Bảng sản phẩm để thay đổi danh mục của sản phẩm phản ánh ngay lập tức trên Điều khiển ListView.

Bảng dữ liệu demo được lấy từ Cơ sở dữ liệu mẫu của Microsoft Access Northwind.accdb và được chia thành hai phần.

Dựa trên Giá trị trường ParentID của bản ghi lvProduct, chúng tôi có thể lọc và liệt kê tất cả các mục sản phẩm có liên quan trong Điều khiển ListView, khi một Nút danh mục được chọn trên Điều khiển TreeView.

Các chủ đề chúng tôi đã đề cập cho đến nay.

Sau đây là các Chủ đề chính trên TreeView , Danh sách hình ảnh , ImageCombo, ListView Các biện pháp kiểm soát, chúng tôi đã đề cập cho đến nay trong MS-Access:

  1. Hướng dẫn Điều khiển Microsoft TreeView
  2. Tạo Menu Truy cập với Điều khiển TreeView
  3. Gán hình ảnh cho điều khiển TreeView
  4. Gán hình ảnh cho TreeView Control-2
  5. Kiểm soát TreeView Kiểm tra-Đánh dấu Thêm nút Xóa
  6. Trình đơn truy cập thả xuống TreeView ImageCombo
  7. Sắp xếp lại các nút TreeView bằng cách kéo và thả
  8. Kiểm soát ListView với MS-Access TreeView

Tác vụ kéo thả ListView.

Liên quan đến hoạt động Kéo và thả của ListView, đây là một bài tập đơn giản so sánh cùng một phương pháp trong Điều khiển TreeView. Vì hành động Kéo thả liên quan đến cả Điều khiển TreeView và ListView, chúng tôi sử dụng cùng một Quy trình sự kiện TreeView0_OLEDragDrop () với một số mã VBA đơn giản.

Các mục Sản phẩm được liệt kê trong Điều khiển ListView thuộc về mục Danh mục hiện tại được chọn trong Điều khiển TreeView.

Người dùng chọn một mục sản phẩm cụ thể từ Điều khiển ListView, nếu họ cho rằng nó thuộc về một Mục danh mục khác, thì hãy kéo và thả nó vào mục Danh mục mục tiêu trên TreeViewCcontrol.

Mục Sản phẩm ListView đã di chuyển sẽ được thêm vào danh sách các mặt hàng thuộc Danh mục đã thay đổi. Giá trị trường ParentID của bản ghi sản phẩm được cập nhật với ID bản ghi Danh mục mục tiêu (giá trị CID).

Đây chỉ là hành động một chiều, luôn di chuyển mục ListView từ một danh mục và thả nó vào một Nút danh mục khác trên Điều khiển TreeView.

Bản trình diễn kéo thả ListView Biểu mẫu truy cập frmListViewDrag ’ s chạy thử Hình ảnh màn hình được cung cấp dưới đây:

Trong Hình ảnh trên, Đồ uống Danh mục trên TreeView đã được chọn. Các sản phẩm thuộc danh mục Đồ uống đã được liệt kê trong Kiểm soát ListView.

Chế độ xem thiết kế của biểu mẫu trên:

Danh sách tên Kiểm soát trên Biểu mẫu như được cung cấp bên dưới:

  1. Điều khiển TreeView: TreeView0
  2. Điều khiển ListView: ListView0
  3. Kiểm soát ImageList: ImageList3
  4. Nút lệnh: cmdClose

Mã VBA trên frmListViewDrag Mô-đun lớp học của:

Option Compare Database
Option Explicit

Dim tv As MSComctlLib.TreeView
Dim lvList As MSComctlLib.ListView
Dim imgList As MSComctlLib.ImageList
Const Prfx As String = "X"

Private Sub Form_Load()
Dim db As DAO.Database
Dim tbldef As TableDef

    Set tv = Me.TreeView0.Object
    tv.Nodes.Clear
    
    Set imgList = Me.ImageList3.Object
    
With tv
    .Font.Size = 9
    .Font.Name = "Verdana"
    .ImageList = imgList 'assign preloaded imagelist control
 End With
    
    Set lvList = Me.ListView0.Object
    lvList.ColumnHeaders.Clear
    lvList.ListItems.Clear
    lvList.Icons = imgList
    
    Set db = CurrentDb
    Set tbldef = db.TableDefs("lvProducts")
    
    'Initialize ListView & Column Headers Property Values
     With lvList
        .ColumnHeaderIcons = imgList
        .Font.Size = 9
        .Font.Name = "Verdana"
        .Font.Bold = False
        
        'ColumnHeaders.Add() Syntax:
        'lvList.ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon
        'Alignment: 0 - Left, 1 - Right, 2 - Center
        .ColumnHeaders.Add 1, , tbldef.Fields(1).Name, 2600, 0, 5
        .ColumnHeaders.Add 2, , tbldef.Fields(3).Name, 2600, 0, 5
        .ColumnHeaders.Add 3, , tbldef.Fields(4).Name, 1440, 1, 5
    End With
    
    Set db = Nothing
    Set tbldef = Nothing

    
   LoadTreeView 'Create TreeView Nodes

End Sub

Private Sub LoadTreeView()
    Dim Nod As MSComctlLib.Node
    Dim firstCatID As Long
    Dim strCategory As String
    Dim strCatKey As String
    Dim strBelongsTo As String
    Dim strSQL As String
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    
    'Initialize treeview nodes
     tv.Nodes.Clear
     
    'Initialize Listview nodes
    While lvList.ListItems.Count > 0
          lvList.ListItems.Remove (1)
    Wend
    
    strSQL = "SELECT lvCategory.CID, lvCategory.Category, "
    strSQL = strSQL & "lvcategory.BelongsTo FROM lvCategory ORDER BY lvCategory.CID;"
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    If Not rst.BOF And Not rst.EOF Then
        rst.MoveFirst
        firstCatID = rst!CID
    Else
        Exit Sub
    End If
    ' Populate all Records as Rootlevel Nodes
    Do While Not rst.BOF And Not rst.EOF
            strCatKey = Prfx & CStr(rst!CID)
            strCategory = rst!Category
            
            Set Nod = tv.Nodes.Add(, , strCatKey, strCategory, 1, 2)
            Nod.Tag = rst!CID
        rst.MoveNext
    Loop
    
    'In the second pass of the the same set of records
    'Move Child Nodes under their Parent Nodes
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
        strBelongsTo = Nz(rst!BelongsTo, "")
        If Len(strBelongsTo) > 0 Then
            strCatKey = Prfx & CStr(rst!CID)
            strBelongsTo = Prfx & strBelongsTo
            strCategory = rst!Category
            
            Set tv.Nodes.Item(strCatKey).Parent = tv.Nodes.Item(strBelongsTo)
        End If
        rst.MoveNext
    Loop
    rst.Close
    
    ' Populate ListView Control with Product details
    ' of the first Category Item
    LoadListView firstCatID
    
End Sub


Private Sub LoadListView(ByVal CatID)
    Dim strProduct As String
    Dim strPKey As String
    Dim intcount As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim strSQL As String
    
    ' Initialize ListView Control
    While lvList.ListItems.Count > 0
        lvList.ListItems.Remove (1)
    Wend
   
     strSQL = "SELECT lvProducts.* FROM lvProducts "
     strSQL = strSQL & "WHERE (lvProducts.ParentID = " & CatID & ") "
     strSQL = strSQL & "ORDER BY lvProducts.[Product Name];"
    
    'Open filtered Products List for selected category
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    Do While Not rst.BOF And Not rst.EOF
        intcount = intcount + 1
        strProduct = rst![Product Name]
        strPKey = Prfx & CStr(rst!PID)
        
        'List Item Add() Syntax:
        'lvList.ListItems.Add Index,Key,Text,Icon,SmallIcon
        Set tmpLItem = lvList.ListItems.Add(, strPKey, strProduct, , 3) 'first column
            lvList.ForeColor = vbBlue
            
            'List second column sub-item Syntax:
            'tmpLItem.ListSubItems.Add Column - Index, Key, Text, ReportIcon, ToolTipText
            tmpLItem.ListSubItems.Add 1, strPKey & CStr(intcount), Nz(rst![Quantity Per Unit], ""), 6
            
            'List third column sub-item
            tmpLItem.ListSubItems.Add 2, strPKey & CStr(intcount + 1), Format(rst![list Price], "0.00"), 6, "In Local Currency."
        rst.MoveNext
    Loop
    
    Set db = Nothing
    Set rst = Nothing
    
    If intcount > 0 Then lvList.ListItems(1).Selected = True
    
End Sub

Private Sub TreeView0_NodeClick(ByVal Node As Object)
Dim Cat_ID As String
Cat_ID = Node.Tag

LoadListView Cat_ID

End Sub

Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long)
    Set tv.SelectedItem = Nothing
End Sub

Private Sub TreeView0_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer)
On Error GoTo TreeView0_OLEDragOver_Err

    Dim nodSelected As MSComctlLib.Node
    Dim nodOver As MSComctlLib.Node
    
    If tv.SelectedItem Is Nothing Then
        'Select a node if one is not selected
        Set nodSelected = tv.HitTest(X, Y)
        If Not nodSelected Is Nothing Then
            nodSelected.Selected = True
        End If
    Else
        If tv.HitTest(X, Y) Is Nothing Then
        'do nothing
        Else
            'Highlight the node the mouse is over
            Set nodOver = tv.HitTest(X, Y)
            Set tv.DropHighlight = nodOver
        End If
    End If
    
TreeView0_OLEDragOver_Exit:
Exit Sub

TreeView0_OLEDragOver_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragOver()"
Resume TreeView0_OLEDragOver_Exit
End Sub


Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Private Sub TreeView0_OLECompleteDrag(Effect As Long)
    Set tv.DropHighlight = Nothing
End Sub

Private Sub cmdClose_Click()
    DoCmd.Close
End Sub

Phân đoạn mã VBA quen thuộc.

Trong Form_Load () Quy trình sự kiện, chúng tôi khởi tạo Điều khiển TreeVew, ListView, ImageList. Nó tạo ColumnHeadings của Điều khiển ListView, trước khi điền các mục Danh sách vào Điều khiển Listview. Khi kết thúc quy trình này, chúng tôi gọi chương trình con LoadTreeView ().

LoadTreeView () chương trình con điền các Nút danh mục của sản phẩm trên Điều khiển TreeView, với các bản ghi từ lvCategory Bàn. Tải các nút trên Điều khiển TreeView là một quá trình gồm hai bước. Tại sao nó là như vậy, thay vì làm nó một lần? Khía cạnh này đã được giải thích chi tiết trên một Trang trước đó, liên kết thứ 7 trong danh sách các liên kết được cung cấp ở trên nếu bạn muốn xem qua nó. Việc lặp lại tất cả chúng ở đây có thể không phù hợp.

Ở cuối chương trình con ở trên, LoadListView () chương trình con đã được gọi với Giá trị CID của bản ghi Danh mục đầu tiên 1 làm tham số.

Bản ghi sản phẩm với giá trị trường ParentID 1 đã được lọc và liệt kê trên Điều khiển ListView. Quy trình này đã được giải thích chi tiết trong bài đăng tuần trước, mục thứ 8, trong số Danh sách các liên kết được đưa ra ở trên.

Chương trình con Hành động Kéo-Thả.

Các chương trình con sau được liên kết với hành động Kéo và Thả sẽ được thực thi tự động theo thứ tự được trình bày bên dưới:

  1. TreeView0_OLEStartDrag ()
  2. TreeView0_OLEDragOver ()
  3. TreeView0_OLEDragDrop ()
  4. TreeView0_OLECompleteDrag ()

Các Chương trình con đầu tiên và cuối cùng khởi tạo các Nút có liên quan và đặt lại trạng thái của chúng ở cuối tương ứng.

Chương trình con thứ hai, OLEDragOver () hoạt động giống như Quy trình sự kiện MouseMove và theo dõi chuyển động của chuột trong quá trình kéo-thả. Nó đánh dấu NodeText khi chuột qua một Node và theo dõi quỹ đạo của nó cho đến khi thả nút chuột trái.

Chỉ riêng mã thủ tục TreeView0_OLEDragDrop () được liệt kê bên dưới.

Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Thao tác Kéo thả Từng bước.

Thủ tục TreeView0_OLEDragDrop () thực thi ngay sau khi thả nút chuột trái để hoàn tất Hành động thả. Ở phần đầu của mã, các tham chiếu đang hoạt động và các nút của Target TreeView Node đã được lưu trong tv_nodSource tv_nodTarget biến đối tượng tương ứng.

Tiếp theo, chúng tôi thực hiện kiểm tra, xem ListItem đã bị loại bỏ trên một nút TreeView hợp lệ hay chưa. Nếu nó bị rơi trên cùng một Nút danh mục nguồn hoặc trên một vùng trống trên Điều khiển TreeView thì những động thái này không hợp lệ. Nếu nó đã bị rơi vào vùng trống của Điều khiển TreeView thì tv_nodTarget biến đối tượng sẽ chứa giá trị Không có gì. Trong trường hợp đó, nó hiển thị thông báo và thoát khỏi Chương trình.

Tiếp theo, Giá trị chính của mã nguồn và nút đích của TreeView đang được lưu trong hai Biến chuỗi. Nếu cả hai khóa đều giống nhau thì ListItem được kéo và thả trên Nút mẹ (Nút danh mục) của chính nó trên Điều khiển TreeView. Quá trình thực hiện chương trình bị hủy bỏ để tiếp tục.

Nếu cả hai Khóa đều khác nhau thì đã đến lúc cập nhật thay đổi trên ParentID của Bản ghi sản phẩm với CID của Bản ghi danh mục mục tiêu Mã và làm mới các Mục trong ListView.

Giá trị Khóa của ListItem đã chọn ( PID giá trị trường) đã được lưu trong strListItemKey Biến chuỗi.

CID thực tế của bản ghi Danh mục giá trị trường đã được trích xuất từ ​​Nút đích, bằng cách loại bỏ giá trị ký tự tiền tố X và được lưu trong biến vCatID . Đây là Giá trị mà chúng tôi sẽ cập nhật trên trường ParentID của Bản ghi sản phẩm, để đặt Mục danh sách trong Danh mục mới.

Tương tự, giá trị PID khóa sản phẩm của Mục danh sách đã chọn được trích xuất và lưu trong Biến lngPID . Điều này đã được sử dụng làm tiêu chí để lọc và chọn bản ghi Sản phẩm cụ thể đó để cập nhật trường ParentID với vCatID .

CẬP NHẬT Truy vấn SQL đã được tạo để lọc bản ghi, sử dụng lngPID Mã làm Tiêu chí, để lọc bản ghi Sản phẩm và cập nhật vCatID Giá trị trong P arentID trường.

Thực thi phương pháp của Currentdb đã được gọi với SQL và cập nhật thay đổi.

Điểm nổi bật của nút đã được đặt lại thành Nút nguồn.

Tiếp theo, chương trình con TreeView0_NodeClick () đã được gọi với tv_nodSource như một tham số để phản ánh sự thay đổi trên Điều khiển ListView.

Đóng Nhấp vào nút sẽ đóng Biểu mẫu.

Tải xuống Cơ sở dữ liệu Demo.

Bạn có thể tải xuống cơ sở dữ liệu Demo, chạy thử và nghiên cứu Mã VBA.


CHÚC CÁC BẠN MỘT NĂM MỚI RẤT HẠNH PHÚC.

XỬ LÝ SỰ KIỆN MS-ACCESS

  1. Mô-đun lớp Withevents MS-Access
  2. Chứng kiến ​​và xác định các sự kiện của riêng bạn
  3. Tab hộp văn bản danh sách kết hợp Withevents
  4. Truy cập Mảng Kiểm soát Biểu mẫu và Sự kiện
  5. Truy cập Mảng điều khiển biểu mẫu và sự kiện-2
  6. Truy cập Mảng điều khiển biểu mẫu và sự kiện-3
  7. Withevents trong Mô-đun lớp cho Biểu mẫu con
  8. Withevents trong Mô-đun lớp và Dữ liệu
  9. Withevents và Access Report Event Sink
  10. Withevents và Báo cáo Ẩn dòng
  11. Withevents và Đánh dấu dòng báo cáo
  12. Withevents Texbox và Nút lệnh
  13. Nút lệnh hộp văn bản Withevents
  14. Withevents và Tất cả các loại kiểm soát biểu mẫu



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tạo và truy cập cơ sở dữ liệu và bảng OLTP trong bộ nhớ

  2. Cách chọn Cơ sở dữ liệu thân thiện với người dùng cho Doanh nghiệp của bạn

  3. Access nói chuyện với các nguồn dữ liệu ODBC như thế nào? Phần 2

  4. Có bao nhiêu người dùng có thể truy cập hỗ trợ?

  5. Các câu hỏi cần hỏi trước khi bắt đầu cơ sở dữ liệu