Использование TreeListView в VB.net - PullRequest
0 голосов
/ 28 июня 2018

Я работаю над созданием простого примера использования TreeListView в VB.NET (или хотя бы одного, которому я могу следовать), и столкнулся с проблемой. Когда я запускаю код ниже, все изначально работает. У меня есть дерево владельцев домашних животных с ветвями имен домашних животных. Но после того, как я раскрыл один из узлов и переместил свою мышь, я получил ошибку, сообщающую мне, что я не могу преобразовать строковый объект в объект petowner (мой объектный класс). Я понимаю, что это значит, но VS не сообщает мне, где ошибка, и я не могу поймать ее в ловушку. Я ищу некоторые идеи.

Также: может кто-нибудь сказать мне, правильно ли мое преобразование из C # в VB; в частности, лямбда-функции вместо делегатов в методах 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 голосов
/ 08 февраля 2019

Я уже некоторое время использую TreeListView, и вместо ваших лямбда-функций я использую 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 может вызвать перерисовку, поэтому установка точек останова в коде обновления чревата опасностью. Вместо этого я добавил множество Console.WriteLine, чтобы рассказать мне, что происходит. Это происходит особенно на небольшом экране, где IDE покрывает TreeListView, и после повторного запуска после остановки точки останова у проекта есть , а затем снова , чтобы вызвать repaint, чтобы нарисовать покрытый экран - который возвращается в IDE - который охватывает экран проекта - и вокруг цикла вы идете ..... Поэтому, если вам действительно нужно отладить код обновления, убедитесь, что IDE и экран проекта не перекрываются.

0 голосов
/ 29 июня 2018

Хорошо, я понял это и тоже кое-что узнал (да, я - лол). Прежде всего, я пришел к выводу, что моя проблема заключается в попытке использовать список строк в качестве имен питомцев, и я не создал список пользовательских объектов с именем Pet со свойством Name, которое можно использовать в качестве AspectName для столбца TreeListView, например Вы бы 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, который по существу предоставляет имя питомца в качестве 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
...