在VB.net中使用TreeListView

时间:2018-06-27 21:39:35

标签: .net vb.net treelistview

我正在创建一个简单示例,该示例在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

2 个答案:

答案 0 :(得分: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

但是,您可以通过将Lambda用于AspectGetter方法来解决该问题,该方法实际上将宠物名称提供为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

答案 1 :(得分: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和项目屏幕不会以任何方式重叠。

相关问题