How to use the property grid in a form to edit any Type

霸气de小男生 提交于 2019-12-21 20:25:11

问题


I have an App where I'd like to be able to edit any type (font, colour, point etc.) at run time and use any of the .Net default type editors. (e.g., font/ colour picker).

Rather than re-invent the wheel, I decided to use the property grid control.

If I pass an object of, say font, to the grid, it lists all the fields separately, with no option to open the font picker.

Therefore, I created this generic wrapper class:

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

Instead of passing a font object to the grid, I pass an instance of the wrapper. The property grid then behaves as I would like.

This works, but the problem is, the object could be of any type and I can't code something like -

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

Basically, the information I have is the type's assembly qualified name and a string representation of the object. I then use a type converter to create the object :

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)

If I pass the object to the property grid, it works but it doesn't work if I pass an instance of the wrapper.

I've solved the problem by using reflection.Emit to create a non generic wrapper of the required type on the fly, but I suspect this is over kill.

Any ideas?

ETA:

I had a problem with what do to if I was using the Grid to edit a property, say a Font, that was not already defined.

If i define:

Dim f as Font = Nothing

, and pass that to the wrapper, the property grid displays as expected with (none) and a button with ... to select the font.

My problem was how to do the equivalent of Dim myObject As 'Type' = Nothing, at run-time.

I couldn't find a way to do this, but luckily with the wrapper and my type, it wasn't a problem. I changed Pradeep's code (look at the answers) to :

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

Problem solved!


回答1:


I think this should work. I've tested it in C# and used a converter to get code in VB.net

This is the code in 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


来源:https://stackoverflow.com/questions/1163151/how-to-use-the-property-grid-in-a-form-to-edit-any-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!