Torna al Thread
Namespace lemoncake.samples
Imports System
Imports System.Collections.Generic
Imports System.Collections
Imports System.Text
Imports System.ComponentModel
Public Class BindingListView
Inherits BindingList
Implements IBindingListView, IRaiseItemChangedEvents
Private m_Sorted As Boolean = false
Private m_Filtered As Boolean = false
Private m_FilterString As String = Nothing
Private m_SortDirection As ListSortDirection = ListSortDirection.Ascending
Private m_SortProperty As PropertyDescriptor = Nothing
Private m_SortDescriptions As ListSortDescriptionCollection = New ListSortDescriptionCollection
Private m_OriginalCollection As List = New List
Public Sub New()
MyBase.New
End Sub
Public Sub New(ByVal list As List)
MyBase.New(list)
End Sub
Protected Overrides ReadOnly Property SupportsSearchingCore As Boolean
Get
Return true
End Get
End Property
Protected Overrides ReadOnly Property SupportsSortingCore As Boolean
Get
Return true
End Get
End Property
Protected Overrides ReadOnly Property IsSortedCore As Boolean
Get
Return m_Sorted
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore As ListSortDirection
Get
Return m_SortDirection
End Get
End Property
Protected Overrides ReadOnly Property SortPropertyCore As PropertyDescriptor
Get
Return m_SortProperty
End Get
End Property
Property IBindingListView_Filter As String Implements IBindingListView.Filter
Get
Return m_FilterString
End Get
Set
m_FilterString = value
m_Filtered = true
UpdateFilter
End Set
End Property
ReadOnly Property IBindingListView_SortDescriptions As ListSortDescriptionCollection Implements IBindingListView.SortDescriptions
Get
Return m_SortDescriptions
End Get
End Property
ReadOnly Property IBindingListView_SupportsAdvancedSorting As Boolean Implements IBindingListView.SupportsAdvancedSorting
Get
Return true
End Get
End Property
ReadOnly Property IBindingListView_SupportsFiltering As Boolean Implements IBindingListView.SupportsFiltering
Get
Return true
End Get
End Property
ReadOnly Property IBindingList_AllowNew As Boolean Implements IBindingList.AllowNew
Get
Return CheckReadOnly
End Get
End Property
ReadOnly Property IBindingList_AllowRemove As Boolean Implements IBindingList.AllowRemove
Get
Return CheckReadOnly
End Get
End Property
ReadOnly Property IRaiseItemChangedEvents_RaisesItemChangedEvents As Boolean Implements IRaiseItemChangedEvents.RaisesItemChangedEvents
Get
Return true
End Get
End Property
Protected Overrides Function FindCore(ByVal property As PropertyDescriptor, ByVal key As Object) As Integer
' Simple iteration:
Dim i As Integer = 0
Do While (i < Count)
Dim item As T = Me(i)
If property.GetValue(item).Equals(key) Then
Return i
End If
i = (i + 1)
Loop
Return -1
' Not found
' Alternative search implementation
' using List.FindIndex:
'Predicate<T> pred = delegate(T item)
'{
' if (property.GetValue(item).Equals(key))
' return true;
' else
' return false;
'};
'List<T> list = Items as List<T>;
'if (list == null)
' return -1;
'return list.FindIndex(pred);
End Function
Protected Overrides Sub ApplySortCore(ByVal property As PropertyDescriptor, ByVal direction As ListSortDirection)
m_SortDirection = direction
m_SortProperty = property
Dim comparer As SortComparer = New SortComparer(property, direction)
ApplySortInternal(comparer)
End Sub
Private Sub ApplySortInternal(ByVal comparer As SortComparer)
If (m_OriginalCollection.Count = 0) Then
m_OriginalCollection.AddRange(Me)
End If
Dim listRef As List = CType(Me.Items,List)
If (listRef Is Nothing) Then
Return
End If
listRef.Sort(comparer)
m_Sorted = true
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Protected Overrides Sub RemoveSortCore()
If Not m_Sorted Then
Return
End If
Clear
For Each item As T In m_OriginalCollection
Add(item)
Next
m_OriginalCollection.Clear
m_SortProperty = Nothing
m_SortDescriptions = Nothing
m_Sorted = false
End Sub
Sub IBindingListView_ApplySort(ByVal sorts As ListSortDescriptionCollection) Implements IBindingListView.ApplySort
m_SortProperty = Nothing
m_SortDescriptions = sorts
Dim comparer As SortComparer = New SortComparer(sorts)
ApplySortInternal(comparer)
End Sub
Sub IBindingListView_RemoveFilter() Implements IBindingListView.RemoveFilter
If Not m_Filtered Then
Return
End If
m_FilterString = Nothing
m_Filtered = false
m_Sorted = false
m_SortDescriptions = Nothing
m_SortProperty = Nothing
Clear
For Each item As T In m_OriginalCollection
Add(item)
Next
m_OriginalCollection.Clear
End Sub
Protected Overridable Sub UpdateFilter()
Dim equalsPos As Integer = m_FilterString.IndexOf(Microsoft.VisualBasic.ChrW(61))
' Get property name
Dim propName As String = m_FilterString.Substring(0, equalsPos).Trim
' Get filter criteria
Dim criteria As String = m_FilterString.Substring((equalsPos + 1), (m_FilterString.Length _
- (equalsPos - 1))).Trim
' Strip leading and trailing quotes
criteria = criteria.Substring(1, (criteria.Length - 2))
' Get a property descriptor for the filter property
Dim propDesc As PropertyDescriptor = TypeDescriptor.GetProperties(GetType(T))(propName)
If (m_OriginalCollection.Count = 0) Then
m_OriginalCollection.AddRange(Me)
End If
Dim currentCollection As List = New List(Me)
Clear
For Each item As T In currentCollection
Dim value As Object = propDesc.GetValue(item)
' strip newline characters as it was causing issues with contains
Dim sval As String = value.ToString.Replace(""& vbLf, "").Replace(""& vbCr, "")
If sval.ToString.Contains(criteria) Then
Add(item)
End If
Next
End Sub
Private Function CheckReadOnly() As Boolean
If (m_Sorted OrElse m_Filtered) Then
Return false
Else
Return true
End If
End Function
Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As T)
For Each propDesc As PropertyDescriptor In TypeDescriptor.GetProperties(item)
If propDesc.SupportsChangeEvents Then
propDesc.AddValueChanged(item, OnItemChanged)
End If
Next
MyBase.InsertItem(index, item)
End Sub
Protected Overrides Sub RemoveItem(ByVal index As Integer)
Dim item As T = Items(index)
Dim propDescs As PropertyDescriptorCollection = TypeDescriptor.GetProperties(item)
For Each propDesc As PropertyDescriptor In propDescs
If propDesc.SupportsChangeEvents Then
propDesc.RemoveValueChanged(item, OnItemChanged)
End If
Next
MyBase.RemoveItem(index)
End Sub
Private Sub OnItemChanged(ByVal sender As Object, ByVal args As EventArgs)
Dim index As Integer = Items.IndexOf(CType(sender,T))
OnListChanged(New ListChangedEventArgs(ListChangedType.ItemChanged, index))
End Sub
End Class
Class SortComparer
Inherits IComparer
Private m_SortCollection As ListSortDescriptionCollection = Nothing
Private m_PropDesc As PropertyDescriptor = Nothing
Private m_Direction As ListSortDirection = ListSortDirection.Ascending
Public Sub New(ByVal propDesc As PropertyDescriptor, ByVal direction As ListSortDirection)
MyBase.New
m_PropDesc = propDesc
m_Direction = direction
End Sub
Public Sub New(ByVal sortCollection As ListSortDescriptionCollection)
MyBase.New
m_SortCollection = sortCollection
End Sub
Function IComparer_Compare(ByVal x As T, ByVal y As T) As Integer Implements IComparer.Compare
If (Not (m_PropDesc) Is Nothing) Then
Dim xValue As Object = m_PropDesc.GetValue(x)
Dim yValue As Object = m_PropDesc.GetValue(y)
Return CompareValues(xValue, yValue, m_Direction)
ElseIf ((Not (m_SortCollection) Is Nothing) _
AndAlso (m_SortCollection.Count > 0)) Then
Return RecursiveCompareInternal(x, y, 0)
Else
Return 0
End If
End Function
Private Function CompareValues(ByVal xValue As Object, ByVal yValue As Object, ByVal direction As ListSortDirection) As Integer
Dim retValue As Integer = 0
If (TypeOf xValue Is IComparable) Then
retValue = CType(xValue,IComparable).CompareTo(yValue)
ElseIf (TypeOf yValue Is IComparable) Then
retValue = CType(yValue,IComparable).CompareTo(xValue)
End If
' not comparable, compare String representations
If Not xValue.Equals(yValue) Then
retValue = xValue.ToString.CompareTo(yValue.ToString)
End If
If (direction = ListSortDirection.Ascending) Then
Return retValue
Else
Return (retValue * -1)
End If
End Function
Private Function RecursiveCompareInternal(ByVal x As T, ByVal y As T, ByVal index As Integer) As Integer
If (index >= m_SortCollection.Count) Then
Return 0
End If
' termination condition
Dim listSortDesc As ListSortDescription = m_SortCollection(index)
Dim xValue As Object = listSortDesc.PropertyDescriptor.GetValue(x)
Dim yValue As Object = listSortDesc.PropertyDescriptor.GetValue(y)
Dim retValue As Integer = CompareValues(xValue, yValue, listSortDesc.SortDirection)
If (retValue = 0) Then
Return RecursiveCompareInternal(x, y, ++, index)
Else
Return retValue
End If
End Function
End Class
End Namespace