65.9K
CodeProject 正在变化。 阅读更多。
Home

为 PropertyGrid 添加自定义属性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (214投票s)

2006 年 3 月 31 日

Apache

6分钟阅读

viewsIcon

1746038

downloadIcon

28062

通过 Item 集合扩展 PropertyGrid;通过自定义编辑器、自定义转换器和数据绑定轻松自定义属性。

Sample project

Sample project

引言

在我上一个项目中,我研究了 PropertyGrid 控件,它具有非常漂亮的界面和感觉。我立即注意到使用它有多么困难。在网上搜索,我发现很多人都在渴望更易于使用的东西,比如 TreeViewListView。因此,我开始开发一个扩展版的 PropertyGrid,其中包含一个 Item 集合。

Using the Code

该控件由三个基本类组成

  • CustomProperty 类,代表单个属性。
  • CustomPropertyDescriptor 类,由 PropertyGrid 内部使用以检索属性的属性。
  • CustomPropertyCollection 类,代表 CustomProperty 的集合。

最终,我们得到了 PropertyGridEx 控件,它继承自 PropertyGrid 并公开了一个 Item 集合。要使用该组件,请将其添加到工具箱,然后添加到您的窗体。与经典的 PropertyGrid 相比,我们有一个新的属性可以设置,称为 ShowCustomProperties

Properties

必须将该属性设置为 True,否则该组件将具有与经典 PropertyGrid 相同的行为。

Item 集合

现在我们可以填充自定义属性了。

With Properties
    .Item.Clear()
    .Item.Add("My String", "My Value", False, _
              "Simple type", "This is a string", True)
    .Item.Add("My Integer", 100, False, "Simple type", _
              "This is an integer", True)
    .Item.Add("My Double", 10.4, False, "Simple type", _
              "This is a double", True)
    .Item.Add("My Font", New Font("Arial", 9), False, _
              "Classes", "This is a font class", True)
    .Item.Add("My Color", New Color(), False, _
              "Classes", "This is a color class", True)
    .Item.Add("My Point", New Point(10, 10), False, _
              "Classes", "This is point class", True)
    .Refresh()
End With

CustomProperty 类公开了几个属性,您可以使用它们来个性化您的 PropertyGrid

  • Name,一个表示属性名称的字符串;
  • Value,一个表示属性值的对象;
  • IsReadOnly,一个布尔值,指示属性是否可编辑;
  • Category,一个表示属性显示类别的字符串;
  • Description,一个表示属性描述的字符串,显示在组件底部;
  • Visible,一个布尔值,指示属性是否显示;

最后,请记住在对集合进行任何修改后 Refresh PropertyGrid

Common Properties

文件名编辑器

还可以创建一个 CustomProperty,显示一个对话框来修改文件名。这个技巧是通过 UIFilenameEditor 类实现的,它继承自 System.Drawing.Design.UITypeEditor。您可以创建一个属性,使用众所周知的 FileDialog 作为类型编辑器,如下所示:

With Properties   
    .Clear
    .Item.Add("Filename", "", False, "Misc", "", True)
    .Item(.Item.Count - 1).UseFileNameEditor = True
    .Item(.Item.Count - 1).FileNameDialogType _
                         = FileDialogType.LoadFileDialog
    .Item(.Item.Count - 1).FileNameFilter = _
         "Text files (*.txt)|*.txt|All files (*.*)|*.*"
    .Refresh()
End With

以下是生成的 PropertyGrid。请注意属性值旁边的省略号(Ellipsis)符号,它用于访问 UIFilenameEditor

Filename Editor

自定义选择类型转换器

用户在编辑属性时,希望有一个值列表供其选择,这是一个非常常见的需求。要实现下拉列表,请执行以下操作:

Dim Languages As String() = New String() {"English", _
                                          "Italian", _
                                          "Spanish", _
                                          "Dutch"}
With Properties   
    .Clear
    .Item.Add("Language", "", False, "Misc", "")
    .Item(.Item.Count - 1).Choices _
                         = New CustomChoices(Languages, True)
    .Refresh()
End With

您可以使用 StringIntegerDoubleObject 数组来初始化 Choices 属性。以下是使用 String 数组初始化的 PropertyGrid

Custom Choices TypeConverter

枚举

大多数时候,开发人员会在其代码中声明枚举。该组件会自动显示一个包含来自 Enum 的值的下拉列表。

Public Enum MyEnum
    FirstEntry
    SecondEntry
    ThirdEntry
End Enum

With Properties 
    .Clear
    .Item.Add("Enum", MyEnum.FirstEntry, False, "Misc")
    .Refresh()
End With

以下是生成的 PropertyGrid

Enum Property

可展开对象转换器

使用此 TypeConverter,可以展开嵌套属性。以下是一个显示应用程序设置的示例。

With Properties 
    .Clear
    .Item.Add("My settings", My.MySettings.Default, False, "Misc")
    .Item(.Item.Count - 1).IsBrowsable = True
    .Item(.Item.Count - 1).BrowsableLabelStyle = _
                           BrowsableTypeConverter.LabelStyle.lsEllipsis
    .Refresh()
End With

以下是生成的 PropertyGrid

Expandable Property

密码字段

使用掩码字段,可以隐藏属性的值。结果是通过 PasswordPropertyTextAttribute 属性生成的,这是 .NET Framework v2.0 中新增的。以下是使用它的示例。

With Properties 
    .Clear
    .Item.Add("My Password", "password", False)
    .Item(.Item.Count - 1).IsPassword = True
    .Refresh()
End With

以下是生成的 PropertyGrid

Password Property

动态属性绑定

使用 PropertyGridEx,可以将对象属性绑定到组件。这是通过集合的一个方法实现的,该方法按引用接受一个值参数。通过这种方式,可以自由地混合引用类型和值类型属性。以下示例将网格的 AutosizePropertiesDrawFlatToolbar 属性进行了绑定。

对这些属性值的任何修改都会自动反映到它们所属的对象中。
With Properties 
    .Clear
    .Item.Add("Autosize properties", Properties, "AutoSizeProperties", False, _
              "Dynamic Properties", "This is a dynamic bound property", True)
    .Item.Add("Draw flat toolbar", Properties, "DrawFlatToolbar", False, _
              "Dynamic Properties", "This is a dynamic bound property", True)
    .Refresh()
End With

以下是生成的 PropertyGrid

Dynamic Properties

多个对象属性

此控件提供的另一个功能是同时编辑多个对象属性的能力。这是通过附加到基组件的 SelectedObjects 属性的对象集合实现的。其行为是,网格仅显示数组中所有对象共有的属性。要激活多个对象功能,必须将网格的 ShowCustomPropertiesSet 属性设置为 True

With Properties
    .ShowCustomPropertiesSet = True
    .ItemSet.Clear()

    .ItemSet.Add()
    .ItemSet(0).Add("My Point", New Point(10, 10), False, "Appearance")
    .ItemSet(0).Add("My Date", New Date(2006, 1, 1), False, "Appearance")

    .ItemSet.Add()
    .ItemSet(1).Add("My Point", New Point(10, 10), False, "Appearance")
    .ItemSet(1).Add("My Date", New Date(2007, 1, 1), False, "Appearance")
    .ItemSet(1).Add("My Color", New Color(), False, "Appearance")

    .Refresh()
End With

以下是生成的 PropertyGrid

Multi object Properties

将属性绑定到数据源

将单个属性绑定到数据源是该组件的最新添加功能。创建的包装器接受 CustomProperty 的三个成员:

  • Datasource,要绑定的数据源。
  • DisplayMember(可选),用于绑定下拉控件中显示的列表的字段。
  • ValueMember(可选),用于绑定 CustomProperty 返回的值的字段。
CustomProperty 将返回以下值:
  • Value,表示显示为 System.String 的值。
  • SelectedItem,表示选定的对象,类型为 System.Object
  • SelectedValue,表示选定的值,类型为 System.Object
以下示例创建了三个属性,它们分别绑定了一个 DataTable、一个 Object 数组和一个 String 数组。
With Properties
    .Item.Clear()
    .Item.Add("Datatable", "", False, "Databinding", _
              "This is a UITypeEditor that implement a listbox", True)

    .Item(.Item.Count - 1).ValueMember = "book_Id"
    .Item(.Item.Count - 1).DisplayMember = "title"      
    .Item(.Item.Count - 1).Datasource = LookupTable

    .Item.Add("Array of objects", ListValues(2).Text, False, "Databinding", _
              "This is a UITypeEditor that implement a listbox", True)

    .Item(.Item.Count - 1).ValueMember = "Value"
    .Item(.Item.Count - 1).DisplayMember = "Text"
    .Item(.Item.Count - 1).Datasource = ListValues   

    .Item.Add("Array of strings", Languages(1), False, "Databinding", _
              "This is a UITypeEditor that implement a listbox", True)

    .Item(.Item.Count - 1).Datasource = Languages    
    .Refresh()
End With

请注意,其结果与使用“自定义选择”(使用 TypeConverter)功能实现的结果大不相同。数据绑定功能使用一个实现 ListBox 控件的 UITypeConverter

以下是生成的 PropertyGrid

Properties Databinding

自定义事件编辑器

使用 PropertyGridEx,可以将模态编辑器中使用的 3 个点的按钮绑定到自定义事件处理程序。这是通过 CustomProperty 的一个方法实现的,该方法接受一个 Delegate 作为参数。以下是一个示例:

With Properties 
    .Clear
    .Item.Add("My Custom Event", "(Click me)", False, "Misc", _
              "The component accept custom event handler.", True) 
    .Item(.Item.Count - 1).OnClick = AddressOf Me.CustomEventItem_OnClick     
    .Refresh()
End With

该事件将由此函数处理:

Private Function CustomEventItem_OnClick(ByVal sender As Object, _
                                         ByVal e As EventArgs) As Object 
    MsgBox("You clicked on property '" & sender.CustomProperty.Name & "'", _
           MsgBoxStyle.Information, _
           "Custom Events as UITypeEditor") 
    Return "(Click me again)" 
End Function 

请注意,函数的返回值将是属性的新值。以下是生成的 PropertyGrid

为控件添加样式

在网上和 CodeProject 上搜索,我找到了很多关于这个组件的文章。不幸的是,我不得不将所有内容合并在一起,以使 PropertyGrid 更易于使用。在本节中,您将找到我发现并添加到此项目中的一些小功能。

  • AutoSizeProperties - 自动移动分隔线以更好地适应显示的所有属性。
  • MoveSplitterTo - 按照用户在参数中指定的位置移动分隔线。
  • DocComment - 将注释区域公开为一个控件。
  • DrawFlatToolbar - 绘制一个扁平的工具栏或一个类似 VS 的工具栏。

请注意,最后一个属性会在具有自定义颜色的 Professional Renderer 和 System Renderer 之间切换工具栏的绘制。

最终注释

我希望您觉得这篇文章有用。如果您觉得这篇文章很差、令人讨厌、不正确等,请根据您的看法对文章进行评分。

致谢

感谢 Pascal Higelin 提供属性绑定功能和 C# 版本。
感谢 Suresh Kavan 提供数据绑定功能的想法和测试用例。

参考文献

历史

  • 2006 年 8 月 22 日
    • 添加了 XML 编辑器示例。
  • 2006 年 5 月 31 日
    • 添加了自定义事件编辑器。
    • 添加了 DocComment 接口。
  • 2006 年 5 月 5 日
    • 添加了序列化。
    • 添加了属性数据绑定。
    • 文章已更新。
  • 2006 年 4 月 28 日
    • 添加了 C# 版本。
    • 添加了动态属性绑定。
    • 添加了多个对象功能。
  • 2006 年 4 月 10 日
    • 添加了密码属性并改进了 ToolStrip 的外观。
    • 添加了可展开对象转换器。
    • 添加了自定义选择类型转换器。
    • 添加了文件名编辑器。
  • 2006 年 3 月 31 日 – 首次提交。
© . All rights reserved.