65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Extender 组件扩展菜单项

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.58/5 (5投票s)

2007 年 10 月 18 日

3分钟阅读

viewsIcon

24443

downloadIcon

184

本文将帮助您使用您喜欢的任何对象表示的属性来扩展菜单项。

Screenshot - MenuExtender.jpg

引言

大家好!本文将帮助您使用您喜欢的任何对象表示的属性来扩展菜单项。您只需要在您的窗体上放置一个特殊的 MenuExtender 组件,每个菜单项都将被扩展,并带有一个由您喜欢的任何对象表示的属性。

背景

您可以通过例如从菜单项继承一个类,然后在设计器代码中将您的类更改为这个继承的类来扩展您应用程序中的菜单项。添加到子项的所有属性都将在属性网格中表示。但是,如果您决定使用附加属性来扩展您的菜单项,并且您已经拥有超过 100 个菜单项,那么您可能需要

  1. 只需单击鼠标一次(或将一个组件拖到您的窗体上)即可全部扩展它们
  2. 确保您或其他开发人员将要添加的其他菜单项也将以相同的方式扩展

您还可以添加任何事件,以便扩展菜单项的类可以做出反应(您可以像处理带有事件的任何其他类(如 button)一样创建事件处理程序)。

所有这些都只需将一个特殊的扩展器组件添加到您的窗体即可完成。

Using the Code

首先,我们将构建一个扩展菜单项的自定义类。您需要从组件 (System.ComponentModel.Component) 继承它。

<serializable(), /> _
Public Class Command
    Inherits Component

    '''Your class definition (properties events etc.)

此外,您需要添加一些类属性,例如 TypeConverterEditor。我们需要它们来链接命令类的属性网格编辑器。由于这个类是一个自定义类,并且可以包含我们想要的任何东西,我们需要为它创建我们自己的编辑器。

Public Class CommandEditor
    Inherits System.Drawing.Design.UITypeEditor

首先,从 UITypeEditor 继承我们的编辑器可以从基类获得大部分功能。我们还可以选择我们的编辑器在属性网格中如何显示

Public Overloads Overrides Function GetEditStyle_
    (ByVal context As System.ComponentModel.ITypeDescriptorContext) _
    As UITypeEditorEditStyle
    Return UITypeEditorEditStyle.Modal
End Function

UITypeEditorEditStyle.Modal 告诉我们命令类的编辑窗体将是模态的。如果您愿意,可以将其设为下拉菜单,只需键入 Return UITypeEditorEditStyle.DropDown.
现在我们需要采取 CommandEditor 的最后也是最大的一步,定义它的 EditValue 函数

Public Overloads Overrides Function EditValue_
    (ByVal context As ITypeDescriptorContext, _
    ByVal provider As IServiceProvider, ByVal value As Object) As Object

' Attempts to obtain an IWindowsFormsEditorService.

Dim edSvc As IWindowsFormsEditorService = CType(provider.GetService( _
GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
If edSvc Is Nothing Then
     Return Nothing
End If

我们获得一项特殊服务,以便在属性网格中显示我们的编辑窗体。

' Displays a CommandEditForm Form to get a Command object

Dim form As CommandEditForm
If (Not value Is Nothing) Then
        Dim cmd As Command = CType(value, Command)
        '... some code omitted as it is long and you can see it 

        ' in the source code attached.

        If edSvc.ShowDialog(form) = DialogResult.OK Then
        Return form.ResultCommand
    Else
        ' If we pressed cancel then we should add the same command back.

        ' If we just remove command then it will cause in exception next time

        ' as there will be no object for this menu item.

        Return form.NoChangesCommand
End If

End Function

现在我们从编辑值中获取一个命令,然后以一种非常特殊的方式显示我们的编辑窗体:edSvc.ShowDialog(form)。编辑窗体的代码非常简单,但您应该注意,您不能创建命令的实例来存储其状态。如果这样做,每次在属性网格中打开您的编辑窗体时,您都会在设计器中获得一个新命令。并且由于每个命令都序列化在 Windows 窗体设计器生成的代码中,因此在您打开编辑器 5 次后,您将获得 5 个新命令。为了避免这种情况,您需要将命令状态存储在 CommandEditForm 中。窗体内的所有代码都有很好的注释,并且可以很容易地找出任何单行代码的作用。

当然,该组件非常复杂,但您可以提出问题,我将更新文章,提供更多详细信息和/或立即回答您的问题。

关注点

目前,我对设计模式和重构非常感兴趣。我一直在寻找模式的好例子,并努力编写更好的代码。

© . All rights reserved.