1

我正在尝试将所有项目从 ContextMenuStrip 提取到List(Of ToolStripMenuItem).
我可以获得 DataGridView 的 ContextMenuStrip 的引用,然后 - 使用递归函数 - 我想提取所有 的NameText属性,如果有的话ToolStripMenuItems,不包括。ToolStripSeparators

我使用这段代码:

allItem = New List(Of Control)
Dim lstDbg As List(Of Control) = FindControlRecursive(allItem, form, GetType(DataGridView))

Dim dictRes As New Dictionary(Of String, String)
For Each dbgCtrl As Control In lstDbg
    If dbgCtrl.Name <> "" Then
        For Each mnuStrip As ToolStripItem In dbgCtrl.ContextMenuStrip.Items
            If mnuStrip.GetType() = GetType(ToolStripMenuItem) Then
                Dim lstItem As New List(Of ToolStripMenuItem)
                Dim lstTS As List(Of ToolStripMenuItem) = FindControlRecursive_ContextMenu(lstItem, mnuStrip, GetType(ToolStripMenuItem))
                    For Each item As ToolStripMenuItem In lstTS
                        dictRes.Add(item.Name, item.Text)
                    Next
             End If
        Next
    End If
Next

递归的功能是FindControlRecursive_ContextMenu()

 Public Function FindControlRecursive_ContextMenu(ByVal list As List(Of ToolStripMenuItem), ByVal parent As ToolStripMenuItem, ByVal ctrlType As System.Type) As List(Of ToolStripMenuItem)
    If parent Is Nothing Then Return list
    If parent.GetType Is ctrlType Then
        list.Add(parent)
    End If
    For Each child As ToolStripMenuItem In parent.DropDown.Items
        FindControlRecursive_ContextMenu(list, child, ctrlType)
    Next
    Return list
End Function

它可以工作,但是如果在 DropDown 列表中有一个ToolStripSeparator,我没有该DropDown.Items元素并且该函数会生成异常。

如何跳过 ToolStripSeparators 并使用下一个“孩子”调用递归函数?

4

1 回答 1

1

由于只需要ToolStripMenuItem类型的子项,因此您可以简单地预先过滤 ContextMenuStrip.Items 集合,仅收集该特定类型的项。Collection.OfType([Type])方法通常用于此目的。OfType()仅返回指定类型的项目:ToolStripSeparator不是该类型,因此它不会包含在过滤的集合中(其他组件类型,如 ToolStripTextBox、ToolStripComboBox 等也不会包含)。

递归函数可以是一个迭代器,它返回一个IEnumerable(Of ToolStripMenuItem)产生for each循环中找到的每一项的迭代器。

调用 main 方法,例如:
► SetOption Strict和toOption ExplicitOption InferOn

 Dim cmsItems As Dictionary(Of String, String) = GetAllContextMenuItems(contextMenuStrip1)
Imports System.Linq

Private Function GetAllContextMenuItems(contextMenu As ContextMenuStrip) As Dictionary(Of String, String)
    If contextMenu Is Nothing OrElse (Not contextMenu.HasChildren) Then Return Nothing
    Dim dict = New Dictionary(Of String, String)
    For Each item As ToolStripMenuItem In contextMenu.Items.OfType(Of ToolStripMenuItem)
        dict.Add(item.Name, item.Text)
        For Each subItem In GetSubMenuItems(item)
            dict.Add(subItem.Name, subItem.Text)
        Next
    Next
    Return dict
End Function

Private Iterator Function GetSubMenuItems(parent As ToolStripMenuItem) As IEnumerable(Of ToolStripMenuItem)
    For Each item As ToolStripMenuItem In parent.DropDownItems.OfType(Of ToolStripMenuItem)
        If item.HasDropDownItems Then
            For Each subItem As ToolStripMenuItem In GetSubMenuItems(item)
                Yield subItem
            Next
        Else
            Yield item
        End If
    Next
End Function
于 2020-10-15T11:08:44.467 回答