问题似乎出在 MultiPage 控件的行为上。
我注意到的是,如果我使用 MultiPage_Change 事件从代码中强制复选框的状态(选中或未选中),则会显示复选框。
所以我所做的是创建一个类,该类保存单个页面上所有列表视图的所有复选框的状态,为每个 ListView 实例化该类并将所有内容存储到字典中,使用 newListView.Name 作为键
然后当用户更改页面时,触发的 MultiPage_Change 事件会根据 Dictionary 存储的值重置所有复选框的值。
在 Listview_N_ItemChecked 事件中,一些其他代码会更新存储在 Dictionary 中的项目的状态。
有点麻烦,但很管用。
类(更新):
' Class Name = ComponentsSignalsRecord
Option Explicit
Dim Name As String
' NOTE: Signals(0) will always be empty and status(0) will always be False
Dim Signals() As String
Dim Status() As Boolean
Dim Component As String
Property Let SetComponentName(argName As String)
Component = argName
End Property
Property Get GetComponentName() As String
GetComponentName = Component
End Property
Property Get getSignalName(argIndex) As String
If argIndex >= LBound(Signals) And argIndex <= UBound(Signals) Then
getSignalName = Signals(argIndex)
Else
getSignalName = vbNullString
End If
End Property
Property Get dumpAll() As String()
dumpAll = Signals
End Property
Property Get Count() As Long
Count = UBound(Signals)
End Property
Property Get getStatus(argName As String) As Integer
' returns: -1 = Not Found; 1 = True; 0 = False
getStatus = -1
Dim i As Integer
For i = 0 To UBound(Signals)
If argName = Signals(i) Then getStatus = IIf(Status(i) = True, 1, 0): Exit For
Next
End Property
Property Let setName(argName As String)
Name = argName
End Property
Property Get getName() As String
getName = Name
End Property
Public Sub UncheckAll()
Dim i As Integer
For i = 0 To UBound(Status)
Status(i) = False
Next
End Sub
Public Sub CheckAll()
Dim i As Integer
For i = 0 To UBound(Status)
Status(i) = True
Next
End Sub
Public Sub deleteSignal(argName As String)
Dim spoolSignals() As String
Dim spoolStatus() As Boolean
Dim i As Integer
spoolSignals = Signals
spoolStatus = Status
ReDim Signals(0)
ReDim Status(0)
For i = 1 To UBound(spoolSignals)
If argName <> spoolSignals(i) Then
ReDim Preserve Signals(UBound(Signals) + 1): Signals(UBound(Signals)) = spoolSignals(i)
ReDim Preserve Status(UBound(Status) + 1): Status(UBound(Status)) = spoolStatus(i)
End If
Next
End Sub
Public Sub addSignal(argName As String, argValue As Boolean)
Dim i As Integer
For i = 0 To UBound(Signals)
If argName = Signals(i) Then GoTo bye
Next
ReDim Preserve Signals(UBound(Signals) + 1)
ReDim Preserve Status(UBound(Status) + 1)
Signals(UBound(Signals)) = argName
Status(UBound(Status)) = argValue
bye:
End Sub
Public Sub setStatus(argName As String, argValue As Boolean)
Dim i As Integer
For i = 0 To UBound(Signals)
If argName = Signals(i) Then Status(i) = argValue: Exit For
Next
End Sub
Private Sub Class_Initialize()
ReDim Signals(0)
ReDim Status(0)
End Sub
表单相关代码。模块级别:
Dim myDict As New Dictionary ' the Dictionary
Dim ComponentsSignalsList As ComponentsSignalsRecord ' the Class
对于创建的每个 ListView,每个 MultiPage 页面可能是一个或多个:
Set ComponentsSignalsList = New ComponentsSignalsRecord
ComponentsSignalsList.setName = newListView.name
在循环中为添加的每个单个项目填充列表视图时:
ComponentsSignalsList.addSignal List_Item.Text, List_Item.Checked
每个循环结束,将 Class 实例添加到 Dictionary:
myDict.Add ComponentsSignalsList.getName, ComponentsSignalsList
现在在多页小部件中更改页面时:
Private Sub Controller_MultiPage_Change()
If isLoading Then Exit Sub 'avoid errors and undue behavior while initializing the MultiPage widget
Dim locControl As Control
Dim controlType As String: controlType = "ListView"
With Controller_MultiPage
For Each locControl In .Pages(.value).Controls
If InStr(1, TypeName(locControl), controlType) > 0 Then
Call Check_CheckBoxes(locControl)
End If
Next
End With
End Sub
Private Sub Check_CheckBoxes(argListView As listView)
If argListView.CheckBoxes = False Then Exit Sub 'some ListViews don't have checkboxes
Dim myItem As ListItem
For Each myItem In argListView.ListItems
With myItem
.Checked = myDict.Item(argListView.name).getStatus(.Text)
End With
Next
End Sub
勾选/取消勾选复选框时(注意 ItemChecked 事件处理程序是在另一个类 Public WithEvents 中定义的,其中处理程序调用此方法并传递 ListView ID 和 Item 对象):
Public Sub ListViewsEvents_ItemCheck(argListView As listView, argItem As MSComctlLib.ListItem)
With argItem
myDict.Item((argListView .name).setStatus argName:=.Text, argValue:=.Checked
End With
End Sub