我只是在这里抛砖引玉,这其中好多结果都是参照其他技术人员的一些例子和介绍,不过我始终没有找到全面的介绍(就是事无具细的)不过这样也好,所以只能自己摸索,这其中我也有好多不解之处.
我就按我如何来解决这些问题来写写.
我的自定义对象集合是是继承于CollectionBase的.因为CollectionBase已经实现了ILIST接口,也就是说可能直接绑定到了DataGrid控件.但是在默认情况自定义类的公共属性都会绑定到datagrid.这显然是不符合要求的.
按我们实际使用情况如下:
1.可以指定要绑定的属性.
2.可以控制绑定属性的列位置.
这时通过查msdn发现了接口ItypedList好像可以实现这些要求.通过google也找到一个关于绑定的例子.如何实现itypedlist接口.最重要的接口方法是GetItemProperties,他就能控制你自定义的那些属性可以进行绑定.返回的值是PropertyDescriptorCollection集合,所以我们需要实现一个自定义属性描述的类CustomPropertyDescriptor它的基类是System.ComponentModel.PropertyDescriptor.重写其抽象方法.其中要注意的是IsReadOnly属性,这个属性就可以控制在datagrid控件中是否允许编辑此属性.
CustomPropertyDescriptor的实现
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public Class CustomPropertyDescriptorClass CustomPropertyDescriptor
Inherits System.ComponentModel.PropertyDescriptor
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
Private md_name As String = String.Empty
Private md_pi As System.Reflection.PropertyInfo
Private md_attribute As FieldAttribute
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub New()Sub New(ByVal name As String, ByVal pi As System.Reflection.PropertyInfo)
MyBase.New(name, pi.GetCustomAttributes(GetType(Attribute), True))
Me.md_name = name
Me.md_pi = pi
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Function GetValue()Function GetValue(ByVal component As Object) As Object
'Debug.WriteLine("GetValue")
Return CType(component, EntityBase).GetValue(Me.md_pi.Name)
End Function
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides ReadOnly Property ComponentType()Property ComponentType() As System.Type
Get
Return Me.md_pi.DeclaringType
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides ReadOnly Property PropertyType()Property PropertyType() As System.Type
Get
Return Me.md_pi.PropertyType
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Sub ResetValue()Sub ResetValue(ByVal component As Object)
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Sub SetValue()Sub SetValue(ByVal component As Object, ByVal value As Object)
'Debug.WriteLine("SetValue")
CType(component, EntityBase).SetValue(Me.md_pi.Name, value)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Function CanResetValue()Function CanResetValue(ByVal component As Object) As Boolean
Return False
End Function
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides Function ShouldSerializeValue()Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return False
End Function
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Overrides ReadOnly Property IsReadOnly()Property IsReadOnly() As Boolean
Get
Return Not Me.md_pi.CanWrite
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
End Class
以下强类型集合的实现
Public Class EntityContainer
Inherits CollectionBase
Implements ITypedList, IBindingList
![](/Images/OutliningIndicators/ContractedBlock.gif)
ItypeList接口#Region "ItypeList接口"
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Function GetItemProperties()Function GetItemProperties(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ITypedList.GetItemProperties
![](/Images/OutliningIndicators/InBlock.gif)
If Me.ItemType Is Nothing Then
Throw New PersistenceLayerException("执行绑定失败,没有指定容器的属性ItemType.")
Else
Dim en As EntityBase = Activator.CreateInstance(Me.ItemType)
Return New System.ComponentModel.PropertyDescriptorCollection(en.GetCustomProperties)
End If
End Function
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Function GetListName()Function GetListName(ByVal listAccessors() As System.ComponentModel.PropertyDescriptor) As String Implements System.ComponentModel.ITypedList.GetListName
If Me.ItemType Is Nothing Then
Throw New PersistenceLayerException("执行绑定失败,没有指定容器的属性ItemType.")
Else
Return Me.ItemType.Name
End If
End Function
#End Region
以前就是我的ItypedList接口的实现其中属性ItemType是指定我当前集合中存放的实体类型.我已定义的实体具有方法GetCustomProperties就是用于返回我当前实体那些属性是允许进行绑定的.
![](/Images/OutliningIndicators/ContractedBlock.gif)
IBindingList接口实现#Region "IBindingList接口实现"
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
公共#Region "公共"
''' -----------------------------------------------------------------------------
''' <summary>
''' 将新项添加到列表。
''' </summary>
''' <returns></returns>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Function AddNew()Function AddNew() As Object Implements System.ComponentModel.IBindingList.AddNew
If Not AllowNew Then Throw New InvalidOperationException("AddNew is not allowed.")
Dim en As EntityBase = Activator.CreateInstance(Me.ItemType)
List.Add(en)
![](/Images/OutliningIndicators/InBlock.gif)
'集合发生改变
OnListChanged(New ListChangedEventArgs(ListChangedType.ItemAdded, List.Count - 1))
![](/Images/OutliningIndicators/InBlock.gif)
'注册事件
AddHandler en.RemoveMe, AddressOf Me.RemoveMe
![](/Images/OutliningIndicators/InBlock.gif)
Return en
End Function
![](/Images/OutliningIndicators/InBlock.gif)
Public Event ListChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Implements System.ComponentModel.IBindingList.ListChanged
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取当列表更改或列表中的项更改时是否引发 ListChanged 事件.默认是True
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public ReadOnly Property SupportsChangeNotification()Property SupportsChangeNotification() As Boolean Implements System.ComponentModel.IBindingList.SupportsChangeNotification
Get
Return True
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
#End Region
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
私有#Region "私有"
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 将 PropertyDescriptor 添加到用于搜索的索引。
''' </summary>
''' <param name="property"></param>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub AddIndex()Sub AddIndex(ByVal [Property ]()property] As System.ComponentModel.PropertyDescriptor) Implements System.ComponentModel.IBindingList.AddIndex
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property AllowEdit1()Property AllowEdit1() As Boolean Implements System.ComponentModel.IBindingList.AllowEdit
Get
Return Me.AllowEdit
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property AllowNew1()Property AllowNew1() As Boolean Implements System.ComponentModel.IBindingList.AllowNew
Get
Return Me.AllowNew
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property AllowRemove()Property AllowRemove() As Boolean Implements System.ComponentModel.IBindingList.AllowRemove
Get
Return Me.AllowDelete
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 根据 PropertyDescriptor 和 ListSortDirection 对列表进行排序。
''' </summary>
''' <param name="property"></param>
''' <param name="direction"></param>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub ApplySort()Sub ApplySort(ByVal [Property ]()property] As System.ComponentModel.PropertyDescriptor, ByVal direction As System.ComponentModel.ListSortDirection) Implements System.ComponentModel.IBindingList.ApplySort
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 返回具有给定 PropertyDescriptor 的行的索引。
''' </summary>
''' <param name="property"></param>
''' <param name="key"></param>
''' <returns></returns>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Function Find()Function Find(ByVal [Property ]()property] As System.ComponentModel.PropertyDescriptor, ByVal key As Object) As Integer Implements System.ComponentModel.IBindingList.Find
![](/Images/OutliningIndicators/InBlock.gif)
End Function
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取是否对列表中的项进行排序。
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property IsSorted()Property IsSorted() As Boolean Implements System.ComponentModel.IBindingList.IsSorted
Get
![](/Images/OutliningIndicators/InBlock.gif)
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 从用于搜索的索引中移除 PropertyDescriptor。
''' </summary>
''' <param name="property"></param>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub RemoveIndex()Sub RemoveIndex(ByVal [Property ]()property] As System.ComponentModel.PropertyDescriptor) Implements System.ComponentModel.IBindingList.RemoveIndex
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取排序的方向。
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property SortDirection()Property SortDirection() As System.ComponentModel.ListSortDirection Implements System.ComponentModel.IBindingList.SortDirection
Get
![](/Images/OutliningIndicators/InBlock.gif)
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取列表是否支持排序。
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property SupportsSorting()Property SupportsSorting() As Boolean Implements System.ComponentModel.IBindingList.SupportsSorting
Get
Return False
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取列表是否支持使用 Find 方法进行搜索。默认是False
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property SupportsSearching()Property SupportsSearching() As Boolean Implements System.ComponentModel.IBindingList.SupportsSearching
Get
Return False
End Get
End Property
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 使用 ApplySort 移除任何已应用的排序。
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub RemoveSort()Sub RemoveSort() Implements System.ComponentModel.IBindingList.RemoveSort
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 获取正在用于排序的 PropertyDescriptor。
''' </summary>
''' <value></value>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-02 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private ReadOnly Property SortProperty()Property SortProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.IBindingList.SortProperty
Get
![](/Images/OutliningIndicators/InBlock.gif)
End Get
End Property
#End Region
![](/Images/OutliningIndicators/InBlock.gif)
#End Region
实现了ItypedList接口,虽然我们绑定到datagrid已实现了我们的要求,但是这时,不能编辑,不能添加,不能删除,如果要实现这些功能,我们就需要实现IBindingList接口.这个接口主要是用于是否允许编辑,是否允许移除,排序,查找等,排序和查找我没有实现.
这时我以为现在可以正常的完成了绑定,不过事情还没有完,我在进行编辑的时候,有时会有异常产生,在通过google查询绑定方面的资料时,对集合的项目进行改变时要引ListChanged事件.
所以需要重写CollectionBase的一些方法
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
重写CollectionBase的方法#Region "重写CollectionBase的方法"
'在向 CollectionBase 实例中插入新元素之后执行其他自定义进程。
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Protected Overrides Sub OnInsertComplete()Sub OnInsertComplete(ByVal index As Integer, ByVal value As Object)
OnListChanged(New ListChangedEventArgs(ListChangedType.ItemAdded, index))
End Sub
'在从 CollectionBase 实例中移除元素之后执行其他自定义进程。
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Protected Overrides Sub OnRemoveComplete()Sub OnRemoveComplete(ByVal index As Integer, ByVal value As Object)
OnListChanged(New ListChangedEventArgs(ListChangedType.ItemDeleted, index))
End Sub
'在清除 CollectionBase 实例的内容之后执行其他自定义进程。
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Protected Overrides Sub OnClearComplete()Sub OnClearComplete()
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, 0))
End Sub
'当在 CollectionBase 实例中设置值后执行其他自定义进程。
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Protected Overrides Sub OnSetComplete()Sub OnSetComplete(ByVal index As Integer, ByVal oldValue As Object, ByVal newValue As Object)
OnListChanged(New ListChangedEventArgs(ListChangedType.ItemChanged, index))
End Sub
#End Region
这样这个实体的绑定基本就完成了,不过我在使用过程出现了一些问题,第一个是我不能像datatabel绑定datagrid那样按esc取消编辑,同时存在一些情况,我不能往datagird里输入值,虽然行是添加成功了,百思不得其解.又查资料.如果要实现按esc取消编辑的功能需要对自定义类实现接口IEditableObject.以下是我实现接口的代码
![](/Images/OutliningIndicators/ContractedBlock.gif)
IEditableObject#Region " IEditableObject "
![](/Images/OutliningIndicators/InBlock.gif)
'编辑标志
Private md_Editing As Boolean
'存放当前正在编辑的实例
Private md_editEntity As EntityBase
'当进行绑时,并取消编辑时,移除对象
Private md_IsNew As Boolean = True
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 开始编辑
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-03 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub BeginEdit()Sub BeginEdit() Implements System.ComponentModel.IEditableObject.BeginEdit
If Me.md_IsNew Then
'绑定添加
Else
'绑定编辑
If Not md_Editing Then
Me.md_Editing = True
Me.md_editEntity = Activator.CreateInstance(Me.GetType)
![](/Images/OutliningIndicators/InBlock.gif)
For Each str As String In Me.AttributeList
Me.md_editEntity.SetValue(str, Me.GetValue(str))
Next
End If
End If
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 取消编辑
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-03 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub CancelEdit()Sub CancelEdit() Implements System.ComponentModel.IEditableObject.CancelEdit
![](/Images/OutliningIndicators/InBlock.gif)
'在绑定时移除新增的对象
If Me.md_IsNew Then
RaiseEvent RemoveMe(Me)
Else
For Each str As String In Me.AttributeList
Me.SetValue(str, Me.md_editEntity.GetValue(str))
Next
End If
![](/Images/OutliningIndicators/InBlock.gif)
Me.md_Editing = False
Me.md_IsNew = False
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
''' -----------------------------------------------------------------------------
''' <summary>
''' 结束编辑
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' [zqonline] 2006-09-03 Created
''' </history>
''' -----------------------------------------------------------------------------
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub EndEdit()Sub EndEdit() Implements System.ComponentModel.IEditableObject.EndEdit
Me.md_Editing = False
Me.md_IsNew = False
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
#End Region
![](/Images/OutliningIndicators/None.gif)
注:我的getValue和setValue方法,是我实体自定义的方法.
这时我才把我自定义实体集合进行绑定时,就没有发现问题了.当然还可以实现IDataErrorInfo 接口.这样当用户在操作datagrid时,输入不合法,就会实时给出提示.
同时我也在我的自定义实体集合增加了rest方法.主要是用于通知绑定控件需要进行数据刷新.
'略去部份代码
End Class
完成....
参考文章:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet02252003.asp