1

たぶん、質問には意味がないように見えますが、それは単にこの質問のためです: ObjectListView cast exception (for hit testing)

実行時に、アイテムとサブアイテムを返してコントロールListViewItemに追加する定義済みの関数を使用して、a を定義済みのクラスに変換する方法があるかどうかを知りたいです。ObjectListView

このようなもの:

Dim LVI As New ListViewItem("My Item")
LVI.SubItems.AddRange({"My SubItem 1", "My SubItem 2"})

Dim OwnType = ' ListViewItem transformed into a own type.

FastObjectListView1.SetObjects(OwnType.GET())

ここで@Mur Hafの回答を見ることができますObjectListViewに新しい項目を追加する方法は? 私がやろうとしていることを理解するために、ObjectListview.

4

1 に答える 1

2

songたとえば、事前定義されたクラスが、OLV サイトのモデルの例であるとします。

Public Class Song

    Public Sub New()
        Me.New(String.Empty, DateTime.Now, 0)
    End Sub

    Public Sub New(title As String, lastPlayed As DateTime, rating As Integer)
        Me.Title = title
        Me.LastPlayed = lastPlayed
        Me.Rating = rating
    End Sub

    Public Property Title() As String

    Public Property LastPlayed() As DateTime

    Public Property Rating() As Integer

    Public Function GetSizeInMb() As Single
        Return 1.2
    End Function

End Class

ListViewItem以下は、が移入されていることを前提としています。

  • 題名
    • サイズ
    • 最後にプレイした
    • ランク

OLV メソッドはオブジェクトSetObjectsを受け入れるIEnumerableため、オブジェクトを返すことに注意してくださいList(T)。(OPでリンクされている「Get」メソッドと同じです。)次に、これらの拡張メソッドをModule.

Public Module MyExtensions

    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToSong(item As ListViewItem) As Song
        Dim title As String = item.SubItems(0).Text
        'Dim GetSizeInMb() As Single = Single.Parse(item.SubItems(1).Text) < -Skip, It 's a function in this example.
        Dim lastPlayed = DateTime.Parse(item.SubItems(2).Text)
        Dim rating = Integer.Parse(item.SubItems(3).Text)
        Return New Song(title, lastPlayed, rating)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](view As ListView) As List(Of Song)
        Dim list As New List(Of Song)
        For Each item As ListViewItem In view.Items
            list.Add(item.ToSong())
        Next
        Return list
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](collection As IEnumerable(Of ListViewItem)) As List(Of Song)
        Dim list As New List(Of Song)
        For Each item As ListViewItem In collection
            list.Add(item.ToSong())
        Next
        Return list
    End Function

End Module

利用方法:

シングルListViewItem:

Dim item As ListViewItem = 'Some listviewitem
Me.olvSongs.SetObjects({item.ToSong()})

複数ListViewItem:

Dim item1 As ListViewItem = 'Some listviewitem
Dim item2 As ListViewItem = 'Some listviewitem
Dim item3 As ListViewItem = 'Some listviewitem
Me.olvSongs.SetObjects({item1, item2, item3}.[Get]())

または、に含まれるすべてのアイテムListView:

Dim view As ListView = 'Some listview
Me.olvSongs.SetObjects(view.[Get]())

オプション 2 - 「インターフェイスの方法」

次のオプションはより動的です。IMergable(T)定義済みのクラスにインターフェイスを実装することにより、すべてがGetメソッドをサポートします。

Public Interface IMergable(Of T)
    Sub Merge(item As T)
End Interface

Public Module MyExtensions

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](Of T)(item As ListViewItem) As List(Of T)
        Dim list As New List(Of T)
        Dim obj As T = Activator.CreateInstance(Of T)()
        If (GetType(T).IsAssignableFrom(GetType(IMergable(Of ListViewItem)))) Then
            DirectCast(obj, IMergable(Of ListViewItem)).Merge(item)
            list.Add(obj)
        End If
        Return list
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](Of T)(view As ListView) As List(Of T)
        Dim list As New List(Of T)
        If (GetType(T).IsAssignableFrom(GetType(IMergable(Of ListViewItem)))) Then
            Dim obj As T = Nothing
            For Each item As ListViewItem In view.Items
                obj = Activator.CreateInstance(Of T)()
                DirectCast(obj, IMergable(Of ListViewItem)).Merge(item)
                list.Add(obj)
            Next
        End If
        Return list
    End Function

End Module

実装:

Public Class Song
    Implements IMergable(Of ListViewItem)

    ...

    Private Sub Merge(item As ListViewItem) Implements IMergable(Of ListViewItem).Merge
        If (item Is Nothing) Then
            Throw New ArgumentNullException("item")
        End If
        Me.Title = item.SubItems(0).Text
        'Me.GetSizeInMb = Single.Parse(item.SubItems(1).Text) < -Skip, It 's a function in this example.
        Me.LastPlayed = DateTime.Parse(item.SubItems(2).Text)
        Me.Rating = Integer.Parse(item.SubItems(3).Text)
    End Sub

End Class

利用方法:

Me.olvSongs.SetObjects(myListView.[Get](Of Song)())
Me.olvSongs.SetObjects(myListViewItem.[Get](Of Song)())

Me.olvSongs.SetObjects(myListView.[Get](Of PreDefClassType1)())
Me.olvSongs.SetObjects(myListView.[Get](Of PreDefClassType2)())

オプション 3 - 「反省の道」

この例では、IConvertibleデータ型のみがサポートされています。

Public Module MyExtensions

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](Of T)(view As ListView, ParamArray members As String()) As List(Of T)
        Dim list As New List(Of ListViewItem)
        For Each item As ListViewItem In view.Items
            list.Add(item)
        Next
        Return list.Get(Of T)(members)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](Of T)(item As ListViewItem, ParamArray members As String()) As List(Of T)
        Return New ListViewItem() {item}.Get(Of T)(members)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Get](Of T)(collection As IEnumerable(Of ListViewItem), ParamArray members As String()) As List(Of T)
        Dim list As New List(Of T)
        Dim length As Integer = (members.Length - 1)
        If (length > -1) Then

            Dim type As Type = GetType(T)
            Dim info As KeyValuePair(Of MemberInfo, Type)() = New KeyValuePair(Of MemberInfo, Type)(length) {}

            For index As Integer = 0 To length
                For Each m As MemberInfo In type.GetMember(members(index), (MemberTypes.Method Or MemberTypes.Property), (BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.DeclaredOnly))
                    If (m.MemberType = MemberTypes.Property) Then
                        With DirectCast(m, PropertyInfo)
                            If (.CanWrite AndAlso (.GetIndexParameters().Length = 0)) Then
                                info(index) = New KeyValuePair(Of MemberInfo, Type)(m, .PropertyType)
                                Exit For
                            End If
                        End With
                    ElseIf (m.MemberType = MemberTypes.Method) Then
                        With DirectCast(m, MethodInfo)
                            Dim params As ParameterInfo() = .GetParameters()
                            If (params.Length = 1) Then
                                info(index) = New KeyValuePair(Of MemberInfo, Type)(m, params(0).ParameterType)
                                Exit For
                            End If
                        End With
                    End If
                Next
            Next

            For Each item As ListViewItem In collection
                Dim obj As T = Activator.CreateInstance(Of T)()
                Dim ict As Type = GetType(IConvertible)
                For index As Integer = 0 To length
                    Dim pair As KeyValuePair(Of MemberInfo, Type) = info(index)
                    If (Not pair.Key Is Nothing) Then
                        If (ict.IsAssignableFrom(pair.Value)) Then
                            If (pair.Key.MemberType = MemberTypes.Property) Then
                                DirectCast(pair.Key, PropertyInfo).SetValue(obj, System.Convert.ChangeType(item.SubItems(index).Text, pair.Value), Nothing)
                            Else
                                DirectCast(pair.Key, MethodInfo).Invoke(obj, System.Convert.ChangeType(item.SubItems(index).Text, pair.Value))
                            End If
                        Else
                            'TODO: Support other data types.
                            'If (pair.Key.MemberType = MemberTypes.Property) Then
                            'DirectCast(pair.Key, PropertyInfo).SetValue(obj, item.SubItems(index).Text, Nothing)
                            'Else
                            'DirectCast(pair.Key, MethodInfo).Invoke(obj, New Object() {item.SubItems(index).Text})
                            'End If
                        End If
                    End If
                Next
                list.Add(obj)
            Next

        End If
        Return list
    End Function

End Module

利用方法:

    Me.olvSongs.SetObjects(myListView.[Get](Of Song)("Title", "GetSizeInMb", "LastPlayed", "Rating"))
    Me.olvSongs.SetObjects(myListViewItem.[Get](Of Song)("Title", "GetSizeInMb", "LastPlayed", "Rating"))

    Me.olvSongs.SetObjects(myListView.[Get](Of PreDefClassType1)("Prop1", "Prop2", "Prop3"))
    Me.olvSongs.SetObjects(myListView.[Get](Of PreDefClassType2)("PropA", "PropB", "PropC"))
于 2014-01-01T21:39:09.573 に答える