如何在表单中使用属性网格来编辑任何类型 [英] How to use the property grid in a form to edit any Type

查看:164
本文介绍了如何在表单中使用属性网格来编辑任何类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

与其重新发明轮子,我决定使用属性网格控件。



如果我将一个字体对象传递给网格,它将单独列出所有字段,并且无法打开字体选择器。



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

  Private Class Wrapper(Of T)
Private _Value As T
公共财产价值()作为T
获得
返回Me._Value
结束获取
Set(ByVal value As T)
Me._Value = value
End Set
End Property

公共子新值(ByVal Value As T)
Me._Value =
End Sub
End Class

不是将字体对象传递给网格,而是传递包装器的一个实例。然后,属性网格表现得如我所愿。



这可行,但问题是,对象可能是任何类型的,我不能编码像 - / p>

  Dim MyWrapper =新包装(T)(myObject)。 

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

  Dim ID As String =System.Drawing.Font,System.Drawing ,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a
Dim Property 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)

如果我将该对象传递给属性网格,它可以工作,但如果我传递包装器的实例,则它不起作用。



我已经通过使用reflection解决了这个问题。提供创建所需类型的非泛型包装的动态,但我怀疑这已经结束了。



任何想法?



ETA:



如果我使用网格时遇到问题如果我定义了:

  d im f as Font = Nothing 

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



我的问题是如何在运行时将Dim myObject等同于'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

问题解决!

解决方案

我认为这应该起作用。我已经在C#中测试了它,并使用了一个转换器来获取VB.net中的代码。



这是C#中的代码

 类型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


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!

解决方案

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

这篇关于如何在表单中使用属性网格来编辑任何类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆