VB.Net扩展对象IExtenderProvider

3

好的,我已经为这个问题奋斗了几天,现在已经无计可施... 我正在尝试通过扩展控件添加一个在运行时在属性网格中可见的可浏览属性。不管我做什么,iExtenderProvider似乎并没有真正运行。

iExtenderProvider位于第二个项目中,并且已将其引用添加到主项目中。(以下是代码)

Imports System.ComponentModel
Imports System.Windows.Forms

Public Class ControlArray
             Inherits Component
             Implements IExtenderProvider
    <Browsable(True)> Public ReadOnly Property Count As Integer
        Get
            Return 0
        End Get
    End Property

    Public Function CanExtend(ByVal extendee As Object) As Boolean Implements IExtenderProvider.CanExtend
       Return TypeOf extendee Is Control
    End Function
End Class

我先构建第二个项目,然后回到第一个项目,但我的属性窗口中没有任何内容。我在代码中实例化了一个控件,然后尝试查找我的“Count”属性,但是什么也没有显示。有什么建议可以解决这个问题吗?


这不是实现IExtenderProvider的确切方法 - 有一些东西缺失了。而且,IExtenderProvider在VS IDE中运行良好,但在PropertyGrid中不会,因为它使用反射来获取属性 - 您需要一个TypeConverter。 - Ňɏssa Pøngjǣrdenlarp
澄清一下,ExtenderProvider 用于在 VS 的设计时添加属性。它们不是真正的属性(请参阅添加工具提示文本的语法)。对于运行时,您需要一个 TypeConverter 和一个自定义的 PropertyDescriptor。这些都是很多样板代码,看起来为了一个 RO 属性而付出了很多努力。 - Ňɏssa Pøngjǣrdenlarp
仅仅是一个起点...最终结果将是整合,以便能够在PropertyGrid中访问伪名称,使用户可以在运行时“更改控件名称”。 - Eric Forkrud
1个回答

2

阅读答案前

请确保您已了解:

扩展程序提供器是为其他组件提供属性的组件。由扩展程序提供器提供的属性实际上驻留在扩展程序提供器对象本身中,因此不是它修改的组件的真正属性。

在设计时,该属性显示在属性窗口中。

在运行时,您无法通过组件本身访问该属性。相反,您可以在扩展组件上调用getter和setter方法。

实现扩展程序提供器:

  • Component继承并实现IExtenderProvider接口。
  • 使用装饰器ProvideProperty属性,引入提供的属性和目标控件类型。
  • 在实现CanExtend方法时,对于要为其提供属性的每个控件类型返回true。
  • 实现所提供属性的getter和setter方法。

了解更多

示例

使用下面的代码,您可以实现一个扩展组件 ControlExtender。当您构建代码并将 ControlExtender 实例放置在表单上时,它会扩展所有控件,并为您的控件在属性网格中添加属性ControlExtender1 的 SomeProperty

  1. 向项目中添加一个Component并将其命名为ControlExtender
  2. 然后在ControlExtender.vb中使用以下代码:
Imports System.ComponentModel
Imports System.Windows.Forms

<ProvideProperty("SomeProperty", GetType(Control))>
Public Class ControlExtender
    Inherits Component
    Implements IExtenderProvider
    Private controls As New Hashtable
    Public Function CanExtend(extendee As Object) As Boolean Implements IExtenderProvider.CanExtend
            Return TypeOf extendee Is Control
    End Function

    Public Function GetSomeProperty(control As Control) As String
        If controls.ContainsKey(control) Then
            Return DirectCast(controls(control), String)
        End If

        Return Nothing
    End Function
    Public Sub SetSomeProperty(control As Control, value As String)
        If (String.IsNullOrEmpty(value)) Then
            controls.Remove(control)
        Else
            controls(control) = value
        End If
    End Sub
End Class

注意:您也可以根据需要继承 Control。但在大多数情况下,继承 Component 更为合理。


我至少会“提一下”,你也可以继承,因为这是所有MSDN示例的做法(尽管从控件继承似乎有点奇怪)。 - Ňɏssa Pøngjǣrdenlarp
谢谢。嗯,看来我得想办法将新属性添加到任何控件中。谢谢。 - Eric Forkrud
欢迎。满足这种一般要求有许多解决方案。真正的需求是什么? - Reza Aghaei
我正在尝试为我正在开发的应用程序生成Visual Studio。目前,我可以添加任何控件,然后PropertyGrid将显示所有属性,但不包括名称属性,并且也不会显示任何事件。 - Eric Forkrud
1
@IvanFerrerVilla 是的,不错!我可以确认它;但是即使在C#中,我也可能永远不会将其编写为getSomething/setSomething。 - Reza Aghaei
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接