【问题标题】:How to show menu text in custom ToolStripItem?如何在自定义 ToolStripItem 中显示菜单文本?
【发布时间】:2021-01-15 22:17:43
【问题描述】:

主窗体 VB.Net:

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Me.tsBasket = New System.Windows.Forms.ToolStrip()
        Me.tsiFruit = New System.Windows.Forms.ToolStripDropDownButton()
        Me.tsBasket.SuspendLayout()
        Me.SuspendLayout()
        '
        'tsBasket
        '
        Me.tsBasket.Dock = System.Windows.Forms.DockStyle.None
        Me.tsBasket.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
        Me.tsBasket.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.tsiFruit})
        Me.tsBasket.Location = New System.Drawing.Point(355, 213)
        Me.tsBasket.Name = "tsBasket"
        Me.tsBasket.Size = New System.Drawing.Size(121, 25)
        Me.tsBasket.TabIndex = 5
        '
        'tsiFruit
        '
        Me.tsiFruit.ImageTransparentColor = System.Drawing.Color.Magenta
        Me.tsiFruit.Name = "tsiFruit"
        Me.tsiFruit.Size = New System.Drawing.Size(87, 22)
        Me.tsiFruit.Text = "add fruit"
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(800, 450)
        Me.Controls.Add(Me.tsBasket)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.tsBasket.ResumeLayout(False)
        Me.tsBasket.PerformLayout()
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

    Friend WithEvents tsBasket As ToolStrip
    Friend WithEvents tsiFruit As ToolStripDropDownButton
End Class

表单加载:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim men As New TestTool()
    men.Text = "showmeplease"
    men.Image = Nothing
    men.NewProperty = "BO"

    Dim men2 As New TestTool()
    men2.Text = "showmeplease2"
    men2.Image = Nothing
    men2.NewProperty = "BO2"

    tsiFruit.DropDownItems.Add(men)
    tsiFruit.DropDownItems.Add(men2)
    AddHandler men.Click, AddressOf tsiType_Click
    AddHandler men2.Click, AddressOf tsiType_Click
End Sub

Private Sub tsiType_Click(sender As System.Object, e As System.EventArgs)
    Dim MenuItem As TestTool = DirectCast(sender, TestTool)
    MessageBox.Show(MenuItem.NewProperty & "  " & MenuItem.Text)
End Sub

自定义类:

Public Class TestTool
    Inherits ToolStripItem

    Private newPropertyValue As String
    Public Property NewProperty() As String
        Get
            Return newPropertyValue
        End Get
        Set(ByVal value As String)
            newPropertyValue = value
        End Set
    End Property

    Sub New()

        ' This call is required by the designer.
        ' InitializeComponent()

    End Sub
End Class

在我的自定义类/用户控件上,我得到: The designer must create an instance of type 'System.Windows.Forms.ToolStripItem' but it cannot because the type is declared as abstract. 我没有看到文本出现在菜单项中,但点击事件工作正常。

这是扩展(使用 OO 继承)ToolMenuStrip 以便我可以拥有 Display 值和 Member 值的正确方法吗?我希望能够在不使用 .Tag 的情况下存储对象。

编辑: 我在尝试嵌套菜单时得到:

System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Forms.ToolStripMenuItem' to type 'WindowsApp1.TestTool'.'

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim men As New TestTool()
    men.Text = "showmeplease"
    men.Image = Nothing
    men.NewProperty = "BO"

    Dim men2 As New TestTool()
    men2.Text = "showmeplease2"
    men2.Image = Nothing
    men2.NewProperty = "BO2"

    tsiFruit.DropDownItems.Add(men)
    tsiFruit.DropDownItems.Add(men2)

    Dim TypeMenuItem As TestTool = men.DropDownItems.Add("hh")

    For Each mInfo As String In Moreinfo
        TypeMenuItem.DropDownItems.Add(mInfo, Nothing, AddressOf tsiType_Click)
    Next
    AddHandler men.Click, AddressOf tsiType_Click
    AddHandler men2.Click, AddressOf tsiType_Click
End Sub

Private p_Moreinfo As List(Of String)
Public Property Moreinfo() As List(Of String)
    Get

        Dim test As New List(Of String)
        test.Add("A")
        test.Add("B")
        Return test
    End Get
    Set(ByVal value As List(Of String))
        p_Moreinfo = value
    End Set
End Property

【问题讨论】:

  • 你不应该继承ToolStripMenuItem而不是ToolStripItem吗?
  • @jmcilhinney 谢谢,这很有帮助 我尝试扩展菜单,但遇到类型问题,请参阅编辑
  • @jmcilhinney 我花了几个小时调试但没有运气我得到System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Forms.ToolStripMenuItem' to type 'WindowsApp1.TestTool'.' on`Dim TypeMenuItem As TestTool = men.DropDownItems.Add("hh")``
  • 当然你做了,因为那是那个方法返回的。您必须先创建您的类型的实例,然后再添加它。 Microsoft 的现有代码不会自动创建您的类型的实例。

标签: vb.net


【解决方案1】:

如果您启用Option Strict 检查(您应该),您将在Form1_Load 事件中发现以下行的错误:

' Error: Option Strict On disallows implicit conversions from ToolStrinpItem
' to TestTool.
Dim TypeMenuItem As TestTool = men.DropDownItems.Add("hh")

因为.DropDownItems.Add(String) 重载返回ToolStripItem 而不是TestTool 类型的对象。 .DropDownItems 不继承所有者项目的类型。

' Compiles.
Dim TypeMenuItem As ToolStripItem = men.DropDownItems.Add("hh")

' Compiles.
Dim TypeMenuItem As ToolStripMenuItem = DirectCast(men.DropDownItems.Add("hh"), ToolStripMenuItem)

' Throws System.InvalidCastException.
Dim TypeMenuItem As TestTool = DirectCast(men.DropDownItems.Add("hh"), TestTool)

所以,Load 事件中的代码应该是这样的:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim men As New TestTool With {
        .Text = "showmeplease",
        .NewProperty = "BO"
    }

    Dim men2 As New TestTool With {
        .Text = "showmeplease2",
        .NewProperty = "BO2"
    }

    tsiFruit.DropDownItems.Add(men)
    tsiFruit.DropDownItems.Add(men2)

    Dim TypeMenuItem As New TestTool() With {.NewProperty = "hh", .Text = "SomeText"}

    men.DropDownItems.Add(TypeMenuItem)

    For Each mInfo As String In Moreinfo
        Dim item = New TestTool With {.NewProperty = mInfo, .Text = "SomeText"}
        AddHandler item.Click, AddressOf tsiType_Click
        TypeMenuItem.DropDownItems.Add(item)
    Next

    AddHandler men.Click, AddressOf tsiType_Click
    AddHandler men2.Click, AddressOf tsiType_Click
End Sub

同样,为了避免在tsiType_Click事件中抛出异常,以防万一:

Private Sub tsiType_Click(sender As Object, e As EventArgs)
    Dim item = TryCast(sender, TestTool)

    If item IsNot Nothing Then
        MessageBox.Show($"{item.NewProperty} {item.Text}")
    Else
        MessageBox.Show(DirectCast(sender, ToolStripItem).Text)
    End If
End Sub

我相信您已经修改了TestTool 类,因为@jmcilhinney 对以下内容发表了评论:

Public Class TestTool
    Inherits ToolStripMenuItem

    Sub New()
        MyBase.New
    End Sub

    Public Property NewProperty As String

End Class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    相关资源
    最近更新 更多