-1

将类链接到用户表单的最佳方法是什么?

抱歉是假设性的,但使用实际代码会导致一个页面很长的问题。

假设我有一个包含一个人数据的类。

<<class Person>>
Public FirstName as String
Public LastName as String
Public PhoneNumber as String
<<end class>>

我将该数据放入 VBA 用户窗体列表视图中。

现在,假设如果用户单击列表视图中的该记录,我想将电话号码更改为 555-555-1234。

我可以通过项目单击事件读取与列表视图的交互。

Private Sub lvExample_ItemClick(ByVal Item As MSComctlLib.ListItem)
  ' Change the phone number
End Sub

从上面代码中的 Item 到我的实际对象的最佳方法是什么?我是否应该为每个对象添加一个 GUID 并将其放入列表项的标签中,然后查找它?我是否应该将列表视图中的列表项添加到类中,以便我可以遍历所有人员,然后查看 _ItemClick 中的项目是否等于对象中的项目?

4

3 回答 3

3

最简单的方法是使用 ListItem 的 Index 属性(如果没有任何唯一标识符)或 Key 属性(如果有)。

如果您选择使用 Index 属性,那么您不能(或者至少它会使其变得非常复杂)添加任何功能来重新排列列表项的顺序。

您将通过 ListView.ListItems.Add 方法根据集合/记录集中的对象填充 ListView。您可以使用 Index 属性根据与原始对象集合中的项目顺序相对应的 ListItems 中的项目顺序返回到该原始对象。

或者,如果您更喜欢使用唯一键的更大灵活性但不希望修改底层对象,那么您可以在将每个对象添加到 ListItems 时简单地构造一个唯一键(最简单的是 CStr(一些递增的数字)) ,将键存储在对象旁边。

然后,您可以使用 ListItem 的 .Key 属性。这里的好处是可以允许用户修改其中的项目、删除内容等,而无需使控件无效并重新添加所有对象以保持源中的索引和列表中的索引之间的链接。

例如:

Private persons As Collection
Private Sub lvExample_ItemClick(ByVal Item As MSComctlLib.ListItem)
    ' Change the phone number:

    'Method 1, using the index of listitem within listitems
    'to tie back to index in persons collection
    'Don't allow rearranging/sorting of items with this method for simplicity
    With persons.Item(Item.Index)
        .PhoneNumber = "555-555-1234"
        '...some stuff
    End With

    'Method 2, using a unique key
    'that you generate, as the underlying person object doesn't have a necessarily unique one
    'Items would have been added in a method similar to AddItemsExample1() below
    With persons.Item(Item.Key)
        .PhoneNumber = "555-555-1234"
        '...some stuff
    End With


End Sub

Sub AddItemsExample1()
    'Storage requirements vs. your existing recordset or whatever
    'are minimal as all it is storing is the reference to the underlying
    'person object

    'Adapt per how you have your existing objects
    'But basically get them into a keyed collection/dictionary

    Dim i As Long        
    Set persons = New Collection
    For Each p In MyPersonsSource
        persons.Add p, CStr(i)
        i = i + 1
    Next p

    'By keying them up, you can allow sorting / rearranging
    'of the list items as you won't be working off of Index position

End Sub

最后,如果您将它们放在数据库返回的记录集中,另一种方法是添加一个新字段(我想您有一个现有的对象字段)并在您的记录上运行 UPDATE 查询,用递增的数字填充它(这应该只影响本地记录集(当然首先检查记录集设置!))。以此为关键。

您在对问题的评论中提到您从 SQL 获取数据。对于列表框的所有正常目的,如上所述,通过 Collection 对象运行它们仍然可能是最简单的,但是如果您有例如来自 SQL 的 4 个字段用于记录集中的记录,那么您就没有“对象”在能够调用它的属性的意义上。如果您这样做,请在您的问题或对此的评论中指定,因为可能有更好的方法来回答您的问题,或者实际的更新操作可能需要不同的语法或语义(特别是如果您需要将任何更新传播回来源) :)

于 2013-09-03T23:21:40.507 回答
0

由于您无法更改返回ListItem,因此我有另一个解决方案:

添加与ListItem您的Person课程相关的:

Public FirstName as String
Public LastName as String
Public PhoneNumber as String
Public RelatedObject As Object

填充时TreeView,分配它:

Set SomeListItem = SomeTreeView.ListItems.Add(...)
Set SomePerson.RelatedObject = SomeListItems

因此,每当您更改 a 时ListItem

Private Sub SomeListView_ItemClick(ByVal Item As MSComctlLib.ListItem)
    Dim p As Person
    For Each p In (...)
        If p.RelatedObject Is Item Then
            'Found, p is your person!
            p.PhoneNumber = ...
        End If
    Next
End Sub

或者,如果您不想更改您的Person类,您可以将其封装在另一个类中,例如 PersonToObject:

Public Person As Person
Public RelatedObject As Object

PersonToObject用作链接对象。

于 2013-09-09T14:11:05.687 回答
0

我会使用事件驱动的方法。

Person将具有属性而不是变量,并且分配这些属性将引发事件。

用户表单将具有WithEvents Person,因此相关人员的更改将触发用户表单代码。

人物类:

Public Event Changed()
Private pFirstName As String
Private pLastName As String
Private pPhoneNumber As String

Public Property Get FirstName() As String
    FirstName = pFirstName
End Property

Public Property Let FirstName(ByVal v As String)
    pFirstName = v
    RaiseEvent Changed
End Property

Public Property Get LastName() As String
    LastName = pLastName
End Property

Public Property Let LastName(ByVal v As String)
    pLastName = v
    RaiseEvent Changed
End Property

Public Property Get PhoneNumber() As String
    PhoneNumber = pPhoneNumber
End Property

Public Property Let PhoneNumber(ByVal v As String)
    pPhoneNumber = v
    RaiseEvent Changed
End Property

用户表单中的事件捕获:

Public WithEvents ThisPerson As Person

Private Sub ThisPerson_Changed()
    'Update user form
End Sub

因此,无论何时分配YourForm.RelatedObject = SomePerson,所做的任何更改都SomePerson将触发YourForm.

于 2013-09-09T13:40:31.370 回答