为 PropertyGrid 添加自定义属性






4.94/5 (214投票s)
通过 Item 集合扩展 PropertyGrid;通过自定义编辑器、自定义转换器和数据绑定轻松自定义属性。
- 下载 VB.NET 演示项目 v1.03 - 188 Kb
- 下载 VB.NET 源代码 v1.03 - 45.9 Kb
- 下载 C# 版本(源代码和演示项目)v1.02 - 170 Kb
- 下载 VB.NET 2003 版本(仅源代码)v0.98 - 31.4 Kb
引言
在我上一个项目中,我研究了 PropertyGrid
控件,它具有非常漂亮的界面和感觉。我立即注意到使用它有多么困难。在网上搜索,我发现很多人都在渴望更易于使用的东西,比如 TreeView
或 ListView
。因此,我开始开发一个扩展版的 PropertyGrid
,其中包含一个 Item
集合。
Using the Code
该控件由三个基本类组成
CustomProperty
类,代表单个属性。CustomPropertyDescriptor
类,由PropertyGrid
内部使用以检索属性的属性。CustomPropertyCollection
类,代表CustomProperty
的集合。
最终,我们得到了 PropertyGridEx
控件,它继承自 PropertyGrid
并公开了一个 Item
集合。要使用该组件,请将其添加到工具箱,然后添加到您的窗体。与经典的 PropertyGrid
相比,我们有一个新的属性可以设置,称为 ShowCustomProperties
。
必须将该属性设置为 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
。
文件名编辑器
还可以创建一个 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
。
自定义选择类型转换器
用户在编辑属性时,希望有一个值列表供其选择,这是一个非常常见的需求。要实现下拉列表,请执行以下操作:
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
您可以使用 String
、Integer
、Double
和 Object
数组来初始化 Choices
属性。以下是使用 String
数组初始化的 PropertyGrid
。
枚举
大多数时候,开发人员会在其代码中声明枚举。该组件会自动显示一个包含来自 Enum
的值的下拉列表。
Public Enum MyEnum
FirstEntry
SecondEntry
ThirdEntry
End Enum
With Properties
.Clear
.Item.Add("Enum", MyEnum.FirstEntry, False, "Misc")
.Refresh()
End With
以下是生成的 PropertyGrid
。
可展开对象转换器
使用此 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
。
密码字段
使用掩码字段,可以隐藏属性的值。结果是通过 PasswordPropertyTextAttribute
属性生成的,这是 .NET Framework v2.0 中新增的。以下是使用它的示例。
With Properties
.Clear
.Item.Add("My Password", "password", False)
.Item(.Item.Count - 1).IsPassword = True
.Refresh()
End With
以下是生成的 PropertyGrid
。
动态属性绑定
使用 PropertyGridEx
,可以将对象属性绑定到组件。这是通过集合的一个方法实现的,该方法按引用接受一个值参数。通过这种方式,可以自由地混合引用类型和值类型属性。以下示例将网格的 AutosizeProperties
和 DrawFlatToolbar
属性进行了绑定。
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
。
多个对象属性
此控件提供的另一个功能是同时编辑多个对象属性的能力。这是通过附加到基组件的 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
。
将属性绑定到数据源
将单个属性绑定到数据源是该组件的最新添加功能。创建的包装器接受 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
。
自定义事件编辑器
使用 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 提供数据绑定功能的想法和测试用例。
参考文献
- 充分利用 PropertyGrid 控件
- 在运行时向 PropertyGrid 添加 Item
- 随心所欲地定制 .NET PropertyGrid
- 便捷的类型编辑器:自定义文件名编辑器
- 便捷的类型编辑器:通用下拉编辑器
历史
- 2006 年 8 月 22 日
- 添加了 XML 编辑器示例。
- 2006 年 5 月 31 日
- 添加了自定义事件编辑器。
- 添加了 DocComment 接口。
- 2006 年 5 月 5 日
- 添加了序列化。
- 添加了属性数据绑定。
- 文章已更新。
- 2006 年 4 月 28 日
- 添加了 C# 版本。
- 添加了动态属性绑定。
- 添加了多个对象功能。
- 2006 年 4 月 10 日
- 添加了密码属性并改进了 ToolStrip 的外观。
- 添加了可展开对象转换器。
- 添加了自定义选择类型转换器。
- 添加了文件名编辑器。
- 2006 年 3 月 31 日 – 首次提交。