【问题标题】:collapsible listview可折叠列表视图
【发布时间】:2009-08-25 18:19:44
【问题描述】:

我想让列表视图控件单独折叠到组中。就像在 Vista 的“我的电脑”中一样,只显示组名,然后我们单击该组以展开它。 我正在使用 VB.NET 3.5

【问题讨论】:

    标签: vb.net listview


    【解决方案1】:

    看看这个:

    Collapsible ListViewGroup

    也许:

    Add Group Collapse Behavior on a Listview Control

    两者都是用 C# 编写的,但当然您仍然可以在 VB.NET 项目中使用它们。

    您只能在 Vista 及更高版本上使用这些。

    【讨论】:

      【解决方案2】:

      使用标准的 VB.NET ListView 控件绝对无法做到这一点。事实上,即使使用 ObjectListView 似乎也不可能,这是我遇到 ListView 限制时常用的停靠港。

      你可以:

      1. 滚动您自己的控件
      2. 切换到TreeView
      3. 放弃

      我认为数字 2 是您的最佳选择,因为它并不难。第一个是矫枉过正,需要很多时间。如果您有一个与逻辑层和数据库层紧密耦合的 GUI 层,则转换为 TreeView 可能会困难得多。或者,您可能只是使用其他 ListView 视图。 (在后一种情况下,来自同一个 FOSS 项目的TreeListView 可能是可行的方法——尽管它是 GPL。)

      杀死这个功能可能更容易 - 我认为这不是关键。

      【讨论】:

      • 实际上,ObjectListView 做可折叠组——但它们只适用于 Vista。我认为到目前为止提到的所有解决方案都只能在 Vista 上运行。如果他有 XP,就没有办法让它发生。在这种情况下,您对 TreeListView 的建议可能是他最好的选择。
      • 谢谢!不知道……我在食谱中看不到。
      【解决方案3】:

      这是一篇扩展列表视图的旧文章: http://www.codeproject.com/KB/list/GroupListView.aspx?msg=1135144

      这是一个示例,它使用 GridView、面板和可折叠面板扩展器完成我认为您想要的操作

      您也可以切换到 AJAX 控件工具包 Accordian 控件。

      【讨论】:

        【解决方案4】:

        通过查看你们在此处发布的内容,我设法实现了这一点,这就是我的代码的样子。

        Imports System.Collections.Generic
        Imports System.Text
        Imports System.Windows.Forms
        Imports System.ComponentModel
        Imports System.Runtime.InteropServices
        Imports System.Reflection
        
        Public Class ListViewCollapsible
            Inherits ListView
            Private Const LVM_FIRST As Integer = &H1000
            ' ListView messages
            Private Const LVM_SETGROUPINFO As Integer = (LVM_FIRST + 147)
            ' ListView messages Setinfo on Group
            Private Const WM_LBUTTONUP As Integer = &H202
            ' Windows message left button
            Private Delegate Sub CallBackSetGroupState(lstvwgrp As ListViewGroup, state As ListViewGroupState)
            Private Delegate Sub CallbackSetGroupString(lstvwgrp As ListViewGroup, value As String)
        
            ''' <summary>
            ''' Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message. 
            ''' To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.
            ''' </summary>
            ''' <param name="hWnd">
            ''' [in] Handle to the window whose window procedure will receive the message. 
            ''' If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows. 
            ''' Microsoft Windows Vista and later. Message sending is subject to User Interface Privilege Isolation (UIPI). The thread of a process can send messages only to message queues of threads in processes of lesser or equal integrity level.
            ''' </param>
            ''' <param name="Msg">[in] Specifies the message to be sent.</param>
            ''' <param name="wParam">[in] Specifies additional message-specific information.</param>
            ''' <param name="lParam">[in] Type of LVGROUP, Specifies additional message-specific information.</param>
            ''' <returns>
            ''' Microsoft Windows Vista and later. When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).
            ''' Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a unique message for inter-application communication.
            ''' The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >= WM_USER) to another process, you must do custom marshalling.
            ''' If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.
            ''' Windows 95/98/Me: SendMessageW is supported by the Microsoft Layer for Unicode (MSLU). To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.
            ''' </returns>
            <DllImport("User32.dll"), Description("Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message. To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.")> _
            Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As IntPtr) As Integer
            End Function
        
            Private Shared Function GetGroupID(lstvwgrp As ListViewGroup) As System.Nullable(Of Integer)
                Dim rtnval As System.Nullable(Of Integer) = Nothing
                Dim GrpTp As Type = lstvwgrp.[GetType]()
                If GrpTp IsNot Nothing Then
                    Dim pi As PropertyInfo = GrpTp.GetProperty("ID", BindingFlags.NonPublic Or BindingFlags.Instance)
                    If pi IsNot Nothing Then
                        Dim tmprtnval As Object = pi.GetValue(lstvwgrp, Nothing)
                        If tmprtnval IsNot Nothing Then
                            rtnval = CInt(tmprtnval)
                        End If
                    End If
                End If
                Return rtnval
            End Function
        
            Private Shared Sub setGrpState(lstvwgrp As ListViewGroup, state As ListViewGroupState)
                If Environment.OSVersion.Version.Major < 6 Then
                    'Only Vista and forward allows collaps of ListViewGroups
                    Return
                End If
                If lstvwgrp Is Nothing OrElse lstvwgrp.ListView Is Nothing Then
                    Return
                End If
                If lstvwgrp.ListView.InvokeRequired Then
                    lstvwgrp.ListView.Invoke(New CallBackSetGroupState(AddressOf setGrpState), lstvwgrp, state)
                Else
                    Dim GrpId As System.Nullable(Of Integer) = GetGroupID(lstvwgrp)
                    Dim gIndex As Integer = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp)
                    Dim group As New LVGROUP
                    group.CbSize = Marshal.SizeOf(group)
                    group.State = state
                    group.Mask = ListViewGroupMask.State
                    Dim ip As IntPtr = IntPtr.Zero
                    Try
                        If GrpId IsNot Nothing Then
                            group.IGroupId = GrpId.Value
                            ip = Marshal.AllocHGlobal(group.CbSize)
                            Marshal.StructureToPtr(group, ip, False)
        
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, ip)
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, ip)
                        Else
                            group.IGroupId = gIndex
        
                            ip = Marshal.AllocHGlobal(group.CbSize)
                            Marshal.StructureToPtr(group, ip, False)
        
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, ip)
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, ip)
                        End If
                        lstvwgrp.ListView.Refresh()
                    Finally
                        If (ip <> IntPtr.Zero) Then Marshal.FreeHGlobal(ip)
                    End Try
                End If
            End Sub
        
            Private Shared Sub setGrpFooter(lstvwgrp As ListViewGroup, footer As String)
                If Environment.OSVersion.Version.Major < 6 Then
                    'Only Vista and forward allows footer on ListViewGroups
                    Return
                End If
                If lstvwgrp Is Nothing OrElse lstvwgrp.ListView Is Nothing Then
                    Return
                End If
                If lstvwgrp.ListView.InvokeRequired Then
                    lstvwgrp.ListView.Invoke(New CallbackSetGroupString(AddressOf setGrpFooter), lstvwgrp, footer)
                Else
                    Dim GrpId As System.Nullable(Of Integer) = GetGroupID(lstvwgrp)
                    Dim gIndex As Integer = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp)
                    Dim group As New LVGROUP
                    group.CbSize = Marshal.SizeOf(group)
                    group.PszFooter = footer
                    group.Mask = ListViewGroupMask.Footer
                    Dim ip As IntPtr = IntPtr.Zero
                    Try
                        If GrpId IsNot Nothing Then
                            group.IGroupId = GrpId.Value
                            ip = Marshal.AllocHGlobal(group.CbSize)
                            Marshal.StructureToPtr(group, ip, False)
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, ip)
                        Else
                            group.IGroupId = gIndex
                            ip = Marshal.AllocHGlobal(group.CbSize)
                            Marshal.StructureToPtr(group, ip, False)
                            SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, ip)
                        End If
                    Finally
                        If (ip <> IntPtr.Zero) Then Marshal.FreeHGlobal(ip)
                    End Try
                End If
            End Sub
        
            Public Sub SetGroupState(state As ListViewGroupState)
                For Each lvg As ListViewGroup In Me.Groups
                    setGrpState(lvg, state)
                Next
            End Sub
        
            Public Sub SetGroupState(state As ListViewGroupState, lvg As ListViewGroup)
                setGrpState(lvg, state)
            End Sub
        
            Public Sub SetGroupFooter(lvg As ListViewGroup, footerText As String)
                setGrpFooter(lvg, footerText)
            End Sub
        
            Protected Overrides Sub WndProc(ByRef m As Message)
                If m.Msg = WM_LBUTTONUP Then
                    MyBase.DefWndProc(m)
                End If
                MyBase.WndProc(m)
            End Sub
        End Class
        
        
        ''' <summary>
        ''' LVGROUP StructureUsed to set and retrieve groups.
        ''' </summary>
        ''' <example>
        ''' LVGROUP myLVGROUP = new LVGROUP();
        ''' myLVGROUP.CbSize    // is of managed type uint
        ''' myLVGROUP.Mask  // is of managed type uint
        ''' myLVGROUP.PszHeader // is of managed type string
        ''' myLVGROUP.CchHeader // is of managed type int
        ''' myLVGROUP.PszFooter // is of managed type string
        ''' myLVGROUP.CchFooter // is of managed type int
        ''' myLVGROUP.IGroupId  // is of managed type int
        ''' myLVGROUP.StateMask // is of managed type uint
        ''' myLVGROUP.State // is of managed type uint
        ''' myLVGROUP.UAlign    // is of managed type uint
        ''' myLVGROUP.PszSubtitle   // is of managed type IntPtr
        ''' myLVGROUP.CchSubtitle   // is of managed type uint
        ''' myLVGROUP.PszTask   // is of managed type string
        ''' myLVGROUP.CchTask   // is of managed type uint
        ''' myLVGROUP.PszDescriptionTop // is of managed type string
        ''' myLVGROUP.CchDescriptionTop // is of managed type uint
        ''' myLVGROUP.PszDescriptionBottom  // is of managed type string
        ''' myLVGROUP.CchDescriptionBottom  // is of managed type uint
        ''' myLVGROUP.ITitleImage   // is of managed type int
        ''' myLVGROUP.IExtendedImage    // is of managed type int
        ''' myLVGROUP.IFirstItem    // is of managed type int
        ''' myLVGROUP.CItems    // is of managed type IntPtr
        ''' myLVGROUP.PszSubsetTitle    // is of managed type IntPtr
        ''' myLVGROUP.CchSubsetTitle    // is of managed type IntPtr
        ''' </example>
        ''' <remarks>
        ''' The LVGROUP structure was created by Paw Jershauge
        ''' Created: Jan. 2008.
        ''' The LVGROUP structure code is based on information from Microsoft's MSDN2 website.
        ''' The structure is generated via an automated converter and is as is.
        ''' The structure may or may not hold errors inside the code, so use at own risk.
        ''' Reference url: http://msdn.microsoft.com/en-us/library/bb774769(VS.85).aspx
        ''' </remarks>
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode), Description("LVGROUP StructureUsed to set and retrieve groups.")> _
        Public Structure LVGROUP
            ''' <summary>
            ''' Size of this structure, in bytes.
            ''' </summary>
            <Description("Size of this structure, in bytes.")> _
            Public CbSize As Integer
        
            ''' <summary>
            ''' Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONENo other items are valid.
            ''' </summary>
            <Description("Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONE No other items are valid.")> _
            Public Mask As ListViewGroupMask
        
            ''' <summary>
            ''' Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.
            ''' </summary>
            <Description("Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.")> _
            <MarshalAs(UnmanagedType.LPWStr)> _
            Public PszHeader As String
        
            ''' <summary>
            ''' Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchHeader As Integer
        
            ''' <summary>
            ''' Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.
            ''' </summary>
            <Description("Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.")> _
            <MarshalAs(UnmanagedType.LPWStr)> _
            Public PszFooter As String
        
            ''' <summary>
            ''' Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchFooter As Integer
        
            ''' <summary>
            ''' ID of the group.
            ''' </summary>
            <Description("ID of the group.")> _
            Public IGroupId As Integer
        
            ''' <summary>
            ''' Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.
            ''' </summary>
            <Description("Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.")> _
            Public StateMask As Integer
        
            ''' <summary>
            ''' Flag that can have one of the following values:LVGS_NORMALGroups are expanded, the group name is displayed, and all items in the group are displayed.
            ''' </summary>
            <Description("Flag that can have one of the following values:LVGS_NORMAL Groups are expanded, the group name is displayed, and all items in the group are displayed.")> _
            Public State As ListViewGroupState
        
            ''' <summary>
            ''' Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.
            ''' </summary>
            <Description("Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.")> _
            Public UAlign As UInteger
        
            ''' <summary>
            ''' Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.
            ''' </summary>
            <Description("Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.")> _
            Public PszSubtitle As IntPtr
        
            ''' <summary>
            ''' Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchSubtitle As UInteger
        
            ''' <summary>
            ''' Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.
            ''' </summary>
            <Description("Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.")> _
            <MarshalAs(UnmanagedType.LPWStr)> _
            Public PszTask As String
        
            ''' <summary>
            ''' Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchTask As UInteger
        
            ''' <summary>
            ''' Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
            ''' </summary>
            <Description("Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")> _
            <MarshalAs(UnmanagedType.LPWStr)> _
            Public PszDescriptionTop As String
        
            ''' <summary>
            ''' Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchDescriptionTop As UInteger
        
            ''' <summary>
            ''' Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
            ''' </summary>
            <Description("Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")> _
            <MarshalAs(UnmanagedType.LPWStr)> _
            Public PszDescriptionBottom As String
        
            ''' <summary>
            ''' Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchDescriptionBottom As UInteger
        
            ''' <summary>
            ''' Windows Vista. Index of the title image in the control imagelist.
            ''' </summary>
            <Description("Windows Vista. Index of the title image in the control imagelist.")> _
            Public ITitleImage As Integer
        
            ''' <summary>
            ''' Windows Vista. Index of the extended image in the control imagelist.
            ''' </summary>
            <Description("Windows Vista. Index of the extended image in the control imagelist.")> _
            Public IExtendedImage As Integer
        
            ''' <summary>
            ''' Windows Vista. Read-only.
            ''' </summary>
            <Description("Windows Vista. Read-only.")> _
            Public IFirstItem As Integer
        
            ''' <summary>
            ''' Windows Vista. Read-only in non-owner data mode.
            ''' </summary>
            <Description("Windows Vista. Read-only in non-owner data mode.")> _
            Public CItems As IntPtr
        
            ''' <summary>
            ''' Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.
            ''' </summary>
            <Description("Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.")> _
            Public PszSubsetTitle As IntPtr
        
            ''' <summary>
            ''' Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.
            ''' </summary>
            <Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.")> _
            Public CchSubsetTitle As IntPtr
        End Structure
        
        Public Enum ListViewGroupMask
            None = &H0
            Header = &H1
            Footer = &H2
            State = &H4
            Align = &H8
            GroupId = &H10
            SubTitle = &H100
            Task = &H200
            DescriptionTop = &H400
            DescriptionBottom = &H800
            TitleImage = &H1000
            ExtendedImage = &H2000
            Items = &H4000
            Subset = &H8000
            SubsetItems = &H10000
        End Enum
        
        Public Enum ListViewGroupState
            ''' <summary>
            ''' Groups are expanded, the group name is displayed, and all items in the group are displayed.
            ''' </summary>
            Normal = 0
            ''' <summary>
            ''' The group is collapsed.
            ''' </summary>
            Collapsed = 1
            ''' <summary>
            ''' The group is hidden.
            ''' </summary>
            Hidden = 2
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The group does not display a header.
            ''' </summary>
            NoHeader = 4
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The group can be collapsed.
            ''' </summary>
            Collapsible = 8
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The group has keyboard focus.
            ''' </summary>
            Focused = 16
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The group is selected.
            ''' </summary>
            Selected = 32
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The group displays only a portion of its items.
            ''' </summary>
            SubSeted = 64
            ''' <summary>
            ''' Version 6.00 and Windows Vista. The subset link of the group has keyboard focus.
            ''' </summary>
            SubSetLinkFocused = 128
        
        End Enum
        

        我已经对此进行了测试,它对我来说效果很好。

        希望它也能对你们中的一些人有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 2015-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多