.Designer中的缩写序列化

时间:2015-08-18 11:12:51

标签: .net vb.net visual-studio windows-forms-designer typeconverter

我有一个属性为Foo的自定义控件。我为这个班级创建了一个UITypeEditor

这很有效,可以产生如下设计师代码:

Dim Foo1 As PropertySerialization.Foo = New PropertySerialization.Foo()
Me.FooControl1 = New PropertySerialization.FooControl()
Me.SuspendLayout()
'
'FooControl1
'
Me.FooControl1.Location = New System.Drawing.Point(35, 56)
Me.FooControl1.Name = "FooControl1"
Me.FooControl1.Size = New System.Drawing.Size(188, 136)
Foo1.A = 3
Foo1.B = "World"
Me.FooControl1.Something = Foo1
Me.FooControl1.TabIndex = 0
Me.FooControl1.Text = "FooControl1"

Something属性的类型为Foo,您可以看到设计器明确地创建了一个新对象Foo1

我的问题是:我可以告诉设计师使用With关键字来内联创建foo对象,如:

'
'FooControl1
'
Me.FooControl1.Location = New System.Drawing.Point(35, 56)
Me.FooControl1.Name = "FooControl1"
Me.FooControl1.Size = New System.Drawing.Size(188, 136)
Me.FooControl1.Something = New Foo() With {.A = 3, .B = "World"}
Me.FooControl1.TabIndex = 0
Me.FooControl1.Text = "FooControl1"

我希望在创建更复杂的类型时避免设计器文件中的混乱。

非常感谢C#或VB.NET中的答案。

1 个答案:

答案 0 :(得分:1)

Designer(VS)将把它想象出来并且很大程度上取决于你的Foo类型的构建方式以及它的继承方式。但一般来说,你可以使用构造函数参数提供TypeConverter并至少缩短形式。

这是通过回复InstanceDescriptorCanConvertTo中的ConvertTo来完成的:

<Serializable>
<TypeConverter(GetType(FooConverter))>
Public Class Foo
    Inherits ??????

   <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
   Public Property Name As String

   <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
   Public Property Value As Integer

   Public Sub New(newName As String, v As Integer)
        Name = newName
        Value = v
   End Sub

    ' simple constructor
    Public Sub New()
        Name = "New Foo"
        Value = 0
    End Sub
End Sub

DesignerSerializationVisibility的{​​{1}}属性值告诉VS不要打扰序列化该属性。目的是通过重载的构造函数来处理它。 TypeConverter:

Hidden

为清楚起见,上述内容已明确说明,但您可以使用简写:

Friend Class FooConverter
    Inherits TypeConverter

    ' designer serialization will check to see if 
    ' there is a converter available
    Public Overrides Function CanConvertTo(context As ITypeDescriptorContext,
                                    destType As Type) As Boolean
        If destType = GetType(InstanceDescriptor) Then
            ' Yes I Can!
            Return True
        End If
        Return MyBase.CanConvertTo(context, destType)
    End Function

    Public Overrides Function ConvertTo(context As ITypeDescriptorContext,
                                        info As CultureInfo, value As Object,
                                        destType As Type) As Object

        If destType = GetType(InstanceDescriptor) Then
            Dim f As Foo = CType(value, Foo)

            ' prepare a constructor info
            Dim ctor As Reflection.ConstructorInfo

            ' the ctor wanted, is the one which takes a string, and an Integer
            ctor = GetType(Foo).GetConstructor(New Type() _
                          {GetType(String), GetType(Integer)})

            ' return Instance Descriptor built from ctor info and 
            '   an array of the current values for the ctor
            Return New InstanceDescriptor(ctor,
                        New Object() {f.Name, f.Value}, False)

        End If
        Return MyBase.ConvertTo(context, info, value, destType)
    End Function

End Class

设计器代码结果仍然是一个显式的临时对象,但更紧凑,任何其他属性都将被逐个设置:

Return New InstanceDescriptor(GetType(Foo). _
                              GetConstructor(New Type() _
       {GetType(String),
       GetType(Integer)}),
       New Object() {f.Name, f.Value}, False)

请注意,尾随Dim Foo1 As Prj.Foo = New Prj.Foo("Ziggy", 43) 参数指示VS是否应查找更多属性。属性上BooleanBoolean值的组合将确定VS序列化值还是TC处理它。任何值都希望保留,应由TypeConverter处理或设置为DesignerSerializationVisibility

最后,由于没有关于自定义控件或真实.Visible类型的信息,因此很难知道如何应用某些细节(可序列化等)。

摘自Enhanced CollectionEditor Framework,内容涵盖简单的TC和设计师序列化。

就个人而言,无论VS通常会做什么都可以提供很多额外的工作。