【问题标题】:How to use the property grid in a form to edit any Type如何在表单中使用属性网格来编辑任何类型
【发布时间】:2009-07-22 05:06:00
【问题描述】:

我有一个应用程序,我希望能够在运行时编辑任何类型(字体、颜色、点等)并使用任何 .Net 默认类型编辑器。 (例如,字体/颜色选择器)。

我决定使用属性网格控件,而不是重新发明轮子。

如果我将一个对象(比如字体)传递给网格,它会分别列出所有字段,并且没有打开字体选择器的选项。

因此,我创建了这个通用包装类:

Private Class Wrapper(Of T)
    Private _Value As T
    Public Property Value() As T
        Get
            Return Me._Value
        End Get
        Set(ByVal value As T)
            Me._Value = value
        End Set
    End Property

    Public Sub New(ByVal Value As T)
        Me._Value = Value
    End Sub
End Class

我没有将字体对象传递给网格,而是传递了一个包装器的实例。然后属性网格的行为就像我想要的那样。

这可行,但问题是,对象可以是任何类型,我无法编写类似的代码 -

Dim MyWrapper = New Wrapper(of T)(myObject).

基本上,我拥有的信息是类型的程序集限定名称和对象的字符串表示形式。然后我使用类型转换器来创建对象:

Dim ID As String = "System.Drawing.Font, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
Dim PropertyValue As String = "Arial, 12px, style=Bold, Strikeout"
Dim T As Type = System.Type.GetType(ID)
Dim tc As TypeConverter = TypeDescriptor.GetConverter(T)
Dim o As Object = tc.ConvertFromString(PropertyValue)

如果我将对象传递给属性网格,它会起作用,但如果我传递包装器的实例,它就不起作用。

我已经通过使用反射解决了这个问题。Emit 即时创建所需类型的非泛型包装器,但我怀疑这太过分了。

有什么想法吗?

预计到达时间:

如果我使用 Grid 编辑尚未定义的属性(例如字体),我遇到了问题。

如果我定义:

Dim f as Font = Nothing

,并将其传递给包装器,属性网格按预期显示为 (none) 和一个带有 ... 的按钮以选择字体。

我的问题是如何在运行时执行 Dim myObject As 'Type' = Nothing 的等效操作。

我找不到这样做的方法,但幸运的是,使用包装器和我的类型,这不是问题。 我将 Pradeep 的代码(查看答案)更改为:

Dim genericType As Type = GetType(Wrapper(Of ))
Dim specificType As Type = genericType.MakeGenericType(T)
Dim ci As ConstructorInfo = specificType.GetConstructor(New Type() {T})
Dim wrappedObject As Object = ci.Invoke(New Object() {Nothing})
Me.PropertyGrid1.SelectedObject = wrappedObject

问题解决了!

【问题讨论】:

    标签: vb.net generics editor types propertygrid


    【解决方案1】:

    我认为这应该可行。我已经在 C# 中对其进行了测试,并使用转换器在 VB.net 中获取代码

    这是 C# 中的代码

    Type generic = typeof(Wrapper<>);
    Type specific = generic.MakeGenericType(o.GetType());
    ConstructorInfo ci = specific.GetConstructor(new Type[] { o.GetType() });
    object o1 = ci.Invoke(new object[] { o });
    propertyGrid1.SelectedObject = o1;
    

    VB.NET

    Dim generic As Type =  Type.GetType(Wrapper<>) 
    Dim specific As Type =  generic.MakeGenericType(o.GetType()) 
    Dim ci As ConstructorInfo =  specific.GetConstructor(New Type() {o.GetType() })
    Dim o1 As Object =  ci.Invoke(New Object(){  o })
    propertyGrid1.SelectedObject = o1
    

    【讨论】:

    • 谢谢伙计,这是正确的。我知道我以前使用过类似的东西,但我总是忘记你可以引用没有子类型的泛型类型。我的 28 行 emit 代码现在替换为 4 :-) 稍微更正一下,第一行转换错误,应该是: Dim generic As Type = GetType(Wrapper(Of ))
    猜你喜欢
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多