【问题标题】:Remove TypeNames from property grid expandable group?从属性网格可扩展组中删除 TypeNames?
【发布时间】:2014-12-10 13:21:56
【问题描述】:

问题

我的自定义用户控件的属性组显示类型名称如下:

问题

如何删除它们?

我希望得到与任何其他随机(和专业)用户控件相同的结果,例如不显示垃圾的 krypton 工具集:

代码

这是我如何装饰属性网格的代码示例:

Public Class ElektroListBox : Inherits ListBox

    <Category("Appearance")>
    <Description("Enabled state.")>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    Public ReadOnly Property StateEnabled() As StateLayout
        Get
            Return Me.stateEnabled1
        End Get
    End Property
    Private ReadOnly stateEnabled1 As StateLayout

    Public Sub New()
        Me.stateEnabled1 = New StateLayout(Me)
    End Sub

End Class

<ToolboxItem(False)>
Public Class StateLayout : Inherits Component

    <Category("Appearance")>
    <Description("The item foreground.")>
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    Public ReadOnly Property Items As ItemLayout
        Get
            Return Me.items1
        End Get
    End Property
    Private ReadOnly items1 As ItemLayout

    Public Sub New(ByVal listBox As ElektroListBox)
        Me.items1 = New ItemLayout(listBox1)
    End Sub

End Class

【问题讨论】:

  • 我敢打赌,如果您在对象浏览器中查看 Krypton.StateCommon,它不会继承 Component。组件可以为您做一些事情,但它也有代价。
  • 属性继承自自定义类型,继承自其他氪自定义类型,最后主类型继承自System.Object。
  • System.Object 表示不是从 Component 继承的类。组件为您处理诸如命名和序列化之类的事情,但这种权宜之计是有代价的。使用嵌套 4 深的类型,您的事情也非常复杂。
  • 使用ExpandableObjectConverter 并没有看起来那么难:i.imgur.com/za8Dr3s.jpg(使用之前的一些代码和一个新的 TypeConverter 需要 20 分钟)。另外,您可以摆脱需要引用主机控件的分组类型(这意味着它们与该控件紧密相关)。
  • 谢谢@Plutonix,那么,如果我理解得很好,如果我想通过我想要的自定义来做到这一点,我应该重写所有代码以删除Component 类并“翻译”该类进入ExpandoObject 课程?最后在那些ExpandoObject 类上使用TypeConverter 来自定义(或完全删除,如我所愿)属性网格中显示的信息。我是正确的?我有点迷路了。

标签: .net vb.net winforms class user-controls


【解决方案1】:

从我在这一系列问题中看到的情况是,您正在为已经很复杂的任务(自定义控件)增加复杂性,然后尝试以最简单的方式实现它。这对我来说很少有好的结局。

什么都不做类

以您的 Items/ItemLayout 类为例。它什么都不做,只是为了瓦解两件孤独的事情而存在。将它们表示为 ItemState 的属性同样有效(而且更容易)。每件事只是 Style/StateLayout 的一个属性:

[+] StateEnabled
  [-] Cursor
  [-] ForeColor
  [-] BackColor

如果那些中的每一个也有几个子属性,显然就像你的氪星工具,那么也许我会考虑它。我的意思是,将 BG+FG 折叠为 Item 只会节省一行。

简单与强大

可折叠的东西可以由继承自组件的类型提供。但是从ExpandableObjectConverter 继承的TypeConverter 正是用于折叠属性。一个更简单的模型,可以满足您的大部分需求;从控件类属性开始:

<Browsable(True), EditorBrowsable(EditorBrowsableState.Always),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Property StateEnabled As ItemState

整个状态类:

<TypeConverter(GetType(ItemStateConverter))>
Public Class ItemState
    Inherits ExpandableObjectConverter

    <Browsable(True), NotifyParentProperty(True),
    EditorBrowsable(EditorBrowsableState.Always), DefaultValue(GetType(Color), "")>
    Public Property BackColor As Color

    <Browsable(True), NotifyParentProperty(True),
    EditorBrowsable(EditorBrowsableState.Always), DefaultValue(GetType(Color), "")>
    Public Property ForeColor As Color

    <Browsable(True), NotifyParentProperty(True),
    EditorBrowsable(EditorBrowsableState.Always), DefaultValue(-1)>
    Public Property Pointer As Cursor

    ' serializer requires a simple ctor
    Public Sub New()

    End Sub

    ' see note
    Public Sub New(fg As Color, bg As Color)
        ' default values, if any
        BackColor = bg
        ForeColor = fg
        Pointer = Cursors.Default
    End Sub

End Class

参数化 ctor 允许您使用适用的默认值创建类型:

Public Sub New          ' control ctor
   StateEnabled = New ItemState(SystemColors.WindowText, SystemColors.Window)
   ...

Disabled 和 Selected 道具可以使用 .HighlightText 等作为逻辑起点,而不是 Color.Empty。您可以将自定义控件添加到已经知道来自用户颜色主题的现有颜色的表单中,而不是每次都需要一个一个地设置。

Public Class ItemStateConverter
    Inherits ExpandableObjectConverter

    Public Overrides Function ConvertTo(context As ITypeDescriptorContext,
                               culture As Globalization.CultureInfo,
                               value As Object, destinationType As Type) As Object

        ' need to return something to prevent the
        ' TypeName from displaying.

        If destinationType Is GetType(String) Then
            ' we could provide a Summary of the prop values, but with 3
            ' it gets cluttered:
            '    Dim item As ItemStates = CType(value, ItemStates)

            '    ' ToDo decide the format of collapsed info
            '    Return String.Format("{0}", item.SelectedItem.ForeColor.ToString)

            Return ""
        End If

        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function

End Class

仅此而已。根据类型,VS 将使用您的 TypeConverter 来提供设计器序列化 - 它不仅仅是为 Props 窗口设置样式文本。 Inherit Component 的一个原因是避免这种情况。但是,这里序列化的只是一个Color,VS 可以很好地处理它!

我们希望 this TypeConverter 的主要内容是 ExpandableObjectConverter 提供的摘要/名称覆盖和属性折叠。以上是我必须添加到先前答案中的所有内容:

请注意,如果您像现在一样嵌套事物,那么这种简单性的大部分内容就会消失。 VS 不会/不能深入 subItems 来序列化它们,这意味着你必须编写一个完整的 TypeConverter。为此,我认为StateLayout TypeConverter 在创建InstanceDescriptor 的过程中必须为每个LayoutItem 调用TypeConverter。

上面的设计器代码:

Me.ListBoxEx1.StateEnabled.BackColor = System.Drawing.SystemColors.Window
Me.ListBoxEx1.StateEnabled.ForeColor = System.Drawing.SystemColors.WindowText
Me.ListBoxEx1.StateEnabled.Pointer = System.Windows.Forms.Cursors.Default

杂项

我不确定为什么您的 ItemLayout 是只读的。似乎适得其反:
a) 它要求辅助类型具有对控件的引用,增加了代码和复杂性
b) 它减少了功能

如果您将这些视为StyleSets,则使用该控件的应用程序可以允许用户或开发人员定义样式、保存它们并将它们应用于控件。 ReadOnly 属性可以防止这种情况发生。

  • 所有基于颜色的道具设置器都应该检查Color.Transparent,这可能不太好用。这意味着它们不能真正自动实现,除非用于说明目的。
  • NotifyParent 属性有助于子项通知父类型它已更改。这比对宿主控件的引用更简单。

实现这一点的另一种方法是,它可以提供一个中间立场:

  • 在控件上实现States 集合属性
  • 使用 Enabled、Disabled 和 ReadOnly 类型播种
  • 这会将它们全部折叠到一个属性中,并让他们通过标准集合编辑器和道具网格编辑集合。
  • 唯一的“窍门”是禁用“添加”按钮,但您应该已经有了相应的工具。
  • 或者,让他们定义他们想要的任意数量,并将某些内容简单地映射到 ReadOnlyStyeSet 属性。

【讨论】:

  • (Miscellaneous:) 我在 VS 中使用 Telerik JustCode 扩展来帮助我修复我的命名约定失败和相关的事情,这个扩展告诉我属性应该被声明为只读并且是从构造函数初始化,我一点也不明白,但我相信我的 Telerik 的虚拟老师......哈哈。与往常一样,您提供了很多信息,这不会是我的最后评论,我需要查看并尝试您解释的内容,然后将其标记为已接受,再次感谢。
猜你喜欢
  • 2011-03-02
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 2016-04-05
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
相关资源
最近更新 更多