-1

我正在创建一个在 VB.NET 中使用 TreeListView 的简单示例(或至少一个我可以遵循的示例),但我遇到了一个问题。当我运行下面的代码时,最初一切正常。我有一棵带有宠物名字分支的宠物主人树。但是在我展开其中一个节点并移动鼠标后,我收到一条错误消息,告诉我无法将字符串对象转换为 petowner 对象(我的对象类)。我明白这意味着什么,但 VS 并没有告诉我错误在哪里,我也不能将它困在 try-catch 中。我正在寻找一些见解。

另外:谁能告诉我我从 C# 到 VB 的转换是否正确;特别是 lambda 函数代替 ChildrenGetter 和 AspectGetter 方法中的委托?我相当肯定这就是错误所在。

提前致谢。

Public Class Form1

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

    Dim PetOwners As New List(Of PetOwner)
    Dim PetOwner As PetOwner

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Steve"
    PetOwner.PetNames.Add("Bob the Cat")
    PetOwner.PetNames.Add("Snoop the Dog")
    PetOwners.Add(PetOwner)

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Ann"
    PetOwners.Add(PetOwner)

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Joe"
    PetOwner.PetNames.Add("Shoeless")
    PetOwners.Add(PetOwner)

    Try
        tlvPetOwners.CanExpandGetter = Function(po As PetOwner) po.PetNames.Count > 0
        tlvPetOwners.ChildrenGetter = Function(po As Object)
                                          Dim RetVal As Object = Nothing
                                          Try
                                              If TypeOf po Is PetOwner Then
                                                  RetVal = CType(po, PetOwner).PetNames
                                              Else
                                                  RetVal = po
                                              End If
                                          Catch ex As Exception
                                              Debug.Print(ex.ToString)
                                          Finally

                                          End Try

                                          Return RetVal

                                      End Function


        Dim OwnerColumn As New OLVColumn()


        OwnerColumn.AspectGetter = Function(po As Object)
                                       Dim RetVal As Object = Nothing
                                       Try
                                           If TypeOf po Is PetOwner Then
                                               RetVal = CType(po, PetOwner).OwnerName
                                           Else
                                               RetVal = po
                                           End If
                                       Catch ex As Exception
                                           Debug.Print(ex.ToString)
                                       Finally

                                       End Try

                                       Return RetVal

                                   End Function
        tlvPetOwners.Columns.Add(OwnerColumn)

        tlvPetOwners.Roots = PetOwners
    Catch ex As Exception
        Debug.Print(ex.ToString)
    End Try
End Sub

End Class


Public Class PetOwner
    Public OwnerName As String
    Public  PetNames As New List(Of String)
End Class
4

2 回答 2

0

好的,我想通了,也学到了一些东西(是的,我 - 哈哈)。首先,我得出的结论是我的问题存在于尝试使用字符串列表作为宠物名称,并且没有创建名为 Pet 的自定义对象列表,其属性为 Name 用作 TreeListView 列的 AspectName,例如你会是一个ObjectListView。我不想在我的实际项目中创建一个名称清单(这只是一个测试)。

如果您在 ObjectListView 上尝试这样的操作,您将遇到 AspectName 方法的问题,对于 TreeListView 也是如此。

Private Sub MakeObjectList()

    Dim Pets As New List(Of String)
    Pets.Add("Smokey")
    Pets.Add("Rufus")
    Pets.Add("Petey")
    Pets.Add("Garfield")
    Pets.Add("Ren")
    Pets.Add("Stimpy")
    Pets.Add("Smokey")

    Dim PetCol As New OLVColumn()
    PetCol.Text = "Pets"
    'You would never be able to do this, because you'd have nothing to set it to, and without it your list would never appear.
    'PetCol.AspectGetter = "??????"

    'But using the AspectGetter, you can supply a Lambda, using the pet name itself as the aspect name.
    PetCol.AspectGetter = Function(p As String) p

    olvPets.Columns.Add(PetCol)

    olvPets.SetObjects(Pets)

End Sub

但是,您可以通过对 AspectGetter 方法使用 Lambda 来解决此问题,该方法本质上将宠物名称作为 AspectName 提供。在数据库应用程序中没有用,但如果您只是尝试提供名称清单,则很有用。

然后我决定对 TreeListView 使用这种方法。我确实必须创建第二列来保存宠物名称,并在这样做时将 AspectGetter 设置为:

PetColumn.AspectGetter = Function(po As Object)
                                     Dim RetVal As String
                                     If TypeOf po Is String Then
                                         RetVal = CType(po, String)
                                     Else
                                         RetVal = String.Empty
                                     End If
                                     Return RetVal
                                 End Function

诀窍是这一行:

  RetVal = CType(po, String)

这允许您将字符串本身定义为方面名称。

这是我的最终代码。它由必须放在表单上的 ObjectListView (olvPets) 和 TreeListView (tlvPetOwners) 组成。无论如何,我希望这对其他人有所帮助。

Public Class Form1

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

    MakeTreeView()
    MakeObjectList()

End Sub

Private Sub MakeTreeView()
    Dim PetOwners As New List(Of PetOwner)
    Dim PetOwner As PetOwner

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Steve"
    PetOwner.PetNames.Add("Bob the Cat")
    PetOwner.PetNames.Add("Snoop the Dog")
    PetOwners.Add(PetOwner)

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Ann"
    PetOwners.Add(PetOwner)

    PetOwner = New PetOwner
    PetOwner.OwnerName = "Joe"
    PetOwner.PetNames.Add("Shoeless")
    PetOwners.Add(PetOwner)

    Dim OwnerColumn As New OLVColumn()

    tlvPetOwners.Columns.Add(OwnerColumn)

    Dim PetColumn As New OLVColumn()
    tlvPetOwners.Columns.Add(PetColumn)

    Try
        tlvPetOwners.CanExpandGetter = Function(po As Object)
                                           Dim RetVal As Boolean = False
                                           If TypeOf po Is PetOwner Then
                                               If po.PetNames.Count > 0 Then
                                                   RetVal = True
                                               End If
                                           End If
                                           Return RetVal
                                       End Function

        tlvPetOwners.ChildrenGetter = Function(po As Object) CType(po, PetOwner).PetNames

        OwnerColumn.AspectGetter = Function(po As Object)
                                       Dim RetVal As String = String.Empty
                                       If TypeOf po Is PetOwner Then
                                           RetVal = CType(po, PetOwner).OwnerName
                                       Else
                                           RetVal = String.Empty
                                       End If
                                       Return RetVal
                                   End Function

        PetColumn.AspectGetter = Function(po As Object)
                                     Dim RetVal As String
                                     If TypeOf po Is String Then
                                         RetVal = CType(po, String)
                                     Else
                                         RetVal = String.Empty
                                     End If
                                     Return RetVal
                                 End Function

        tlvPetOwners.SetObjects(PetOwners)
        tlvPetOwners.ExpandAll()

    Catch ex As Exception
        Debug.Print(ex.ToString)
    End Try

End Sub

Private Sub MakeObjectList()

    Dim Pets As New List(Of String)
    Pets.Add("Smokey")
    Pets.Add("Rufus")
    Pets.Add("Petey")
    Pets.Add("Garfield")
    Pets.Add("Ren")
    Pets.Add("Stimpy")
    Pets.Add("Smokey")

    Dim PetCol As New OLVColumn()
    PetCol.Text = "Pets"
    'You would never be able to do this
    'PetCol.AspectGetter = "??????"

    PetCol.AspectGetter = Function(p As String) p

    olvPets.Columns.Add(PetCol)

    olvPets.SetObjects(Pets)

End Sub

End Class

Public Class PetOwner
Public OwnerName As String
Public PetNames As New List(Of String)
End Class
于 2018-06-29T17:10:37.667 回答
0

我已经使用 TreeListView 一段时间了,而不是您的 Lambda 函数,我使用 AddressOf 指向同一空间中的例程..

With tlv

  tlv.BeginUpdate()

  .CanExpandGetter = AddressOf b_tlvCanExpandGetter   ! ***** 
  .ChildrenGetter = AddressOf mcol_GetOccupants       ! *****
  .Roots = colRoot   ' Collection of objects to make the root nodes

  tlv.EndUpdate()

  Application.DoEvents()
  ... etc

然后,指向的例程可以使用任何属性、函数等来做出决定或返回值列表。例如

Function mcol_GetOccupants(ByVal oTI As Object) As List(Of TreeItem)

  Dim ti As TreeItem = CType(oTI, TreeItem)
  Select Case ti.ObjectType

    Case BaseObject.BaseObjectType.eTypeA
      Return CType(oTI, TypeA).Occupants

    Case BaseObject.BaseObjectType.eTypeB,
          BaseObject.BaseObjectType.eTypeC

      Return CType(oTI, TypeBC).Occupants

    Case BaseObject.BaseObjectType.eTypeD
      Return CType(oTI, TypeD).Occupants

    Case Else
      Return New List(Of TreeItem)
  End Select

End Function

我要注意的另一件事是,即使将鼠标移到 TreeListView 上也会触发 RePaint,因此将断点放入刷新代码中充满危险。相反,我放了很多 Console.WriteLine 来告诉我发生了什么。这尤其发生在 IDE 覆盖 TreeListView 的小屏幕上,一旦您在断点停止后再次运行,项目将再次调用 repaint 以绘制其被覆盖的屏幕 - 它会跳回 IDE - 覆盖项目屏幕- 循环你去.....所以,如果你真的需要调试刷新代码,请确保 IDE 和项目屏幕不会以任何方式重叠。

于 2019-02-07T23:48:53.093 回答