在ContextMenuStrip项

时间:2016-01-11 22:36:15

标签: vb.net iterator contextmenustrip

我正在尝试迭代这样的contextmenustrip项目:

Public Sub TranslateContextMenuStrip(ByRef u As ContextMenuStrip)

    For Each t As ToolStripMenuItem In u.Items 'here the error occurs
        pProcessMenuItem(t) 'not here
    Next

End Sub

但是我在contextmenustrip中有工具条分隔符,我收到了错误

“System.InvalidCastException:System.Windows.Forms.ToolStripSeparator类型的对象无法转换为System.Windows.Forms.ToolStripMenuItem类型”

一旦碰到分隔符。

我想知道为什么这个分隔符包含在项目中(我请求“For Each t As ToolStripMenuItem”,为什么它返回非ToolStripMenuItems ???)以及如何捕获此错误或避免它。

2 个答案:

答案 0 :(得分:0)

我不认为For Each t As ToolStripMenuItem会做你认为它做的事情。

它只是声明t迭代器将是ToolStripMenuItem类型。它对项目集合本身没有任何作用。当你来到分隔符时,你会得到强制转换异常,因为分隔符无法转换为菜单项。

ItemsToolStripItem的集合。这是一个基类,用于上下文菜单可以容纳的所有类型(菜单项,组合,文本框或分隔符)。由于这些都继承自ToolStripItem,因此集合可以包含其中任何一个(具体而言,ToolStripSeparator项也是ToolStripItem

有几种方法可以迭代或使用菜单条目:

过滤Items集合

For Each tsi As ToolStripMenuItem In u.Items.OfType(Of ToolStripMenuItem)()
    ' do something fun with tsi
Next

OfType()扩展程序会将项目集合过滤为仅菜单项目。

这是迄今为止最简单的,因为你的迭代器tsi是正确的类型。如果您的方法被编写为期望菜单项,则尤其如此:

Sub pProcessMenuItem(item As ToolStripMenuItem)

tsi迭代器与方法所期望的类型相同,因此不需要进一步的步骤。其他任何东西都需要在方法中进行转换或调用方法(或Option Strict Off)。

测试类型:

' iterate all the items 
For Each tsi As ToolStripItem In u.Items
    ' test the type of each 
    If TypeOf tsi Is ToolStripMenuItem Then
        ' do something fun with tsi
    End If
Next

Option Strict下将tsi传递给上面声明的方法,不会编译。您必须在调用方法之前进行强制转换:

pProcessMenuItem(CType(tsi, ToolStripMenuItem))

如果声明方法接受ToolStripItemObject,则如果您需要访问任何与菜单相关的属性,则必须在方法中进行强制转换。

使用As Object进行迭代也是如此:

For Each it As Object In u.Items
    If TypeOf it Is ToolStripMenuItem Then
        pProcessMenuItem(it)
    End If
Next

如果方法参数声明为Option Strict,则在As Object下编译的唯一方法。如上所述,Object可能必须转换为ToolStripMenuItem。第一种方法可以防止任何需要。

答案 1 :(得分:0)

我找到了一个解决方案,但不是问题:

    For Each it As Object In u.Items
        If TypeOf it Is ToolStripMenuItem Then
            pProcessMenuItem(it)
        End If
    Next