Imports System.ComponentModel
Namespace Controls
Public Class FilterViewFields
Implements IFilterView
Private _view As ICollectionView = Nothing
Private _filter As Predicate(Of Object) = Nothing
Private _getValue As Object = Nothing ' Anonymous function to retrieve a field value
Private _filterText As String = String.Empty
Private _filterTextValues As New List(Of String) ' _filterText split on spaces
Private _matchMode As FilterViewFieldMode = FilterViewFieldMode.AndSegments
Public Property Fields As IEnumerable(Of String) = Nothing
Public Property MatchMode As FilterViewFieldMode
Get
Return _matchMode
End Get
Set(value As FilterViewFieldMode)
_matchMode = value
_filter = Nothing
Select Case _matchMode
Case FilterViewFieldMode.AndSegments : _filter = AddressOf FilterTestAnd
Case FilterViewFieldMode.OrSegments : _filter = AddressOf FilterTestOr
Case FilterViewFieldMode.SimpleMatch : _filter = AddressOf FilterTestSimple
End Select
End Set
End Property
Public Property Filter As Predicate(Of Object) Implements IFilterView.Filter
Get
Return _filter
End Get
Set(value As Predicate(Of Object))
_filter = value
End Set
End Property
Public Property FilterText As String Implements IFilterView.FilterText
Get
Return _filterText
End Get
Set(value As String)
_filterText = value
_filterTextValues.Clear()
For Each w In Split(value, " ")
If Trim(w) <> String.Empty Then
_filterTextValues.Add(w)
End If
Next
End Set
End Property
Public Property View As ICollectionView Implements IFilterView.View
Get
Return _view
End Get
Set(value As ICollectionView)
If value Is _view Then Return
_view = value
_getValue = Nothing
If _view Is Nothing Then Return
Dim src As IEnumerable = _view.SourceCollection
Dim e = src.GetEnumerator
If Not e.MoveNext Then Exit Property
If TypeOf e.Current Is String Then
_getValue = Function(obj As String, fieldName As String) As String
Return obj
End Function
ElseIf TypeOf e.Current Is DataRowView OrElse TypeOf View.CurrentItem Is DataRow Then
_getValue = Function(obj As Object, fieldName As String) As String
If TypeOf obj Is DataRowView Then obj = DirectCast(obj, DataRowView).Row
Dim dr = DirectCast(obj, DataRow)
Return "" & dr(fieldName)
End Function
ElseIf TypeOf e.Current Is Data.List.Row Then
_getValue = Function(obj As Data.List.Row, fieldName As String) As String
Return "" & obj(fieldName)
End Function
ElseIf TypeOf e.Current Is Dynamic.ExpandoObject Then
_getValue = Function(obj As Dynamic.ExpandoObject, field As String) As String
Return "" & DirectCast(obj, IDictionary(Of String, Object))(field)
End Function
ElseIf TypeOf e.Current Is Dynamic.DynamicObject Then
_getValue = Function(obj As Dynamic.DynamicObject, fieldName As String) As String
Return "" & GetDynamicMember(obj, fieldName)
End Function
ElseIf TypeOf e.Current Is IDictionary Then
_getValue = Function(obj As IDictionary, fieldName As String) As String
Return "" & obj(fieldName)
End Function
Else
_getValue = Function(obj As Object, fieldName As String) As String
If obj Is Nothing Then Return String.Empty
Dim pi = obj.GetType.GetProperty(fieldName)
Return "" & pi.GetValue(obj)
End Function
End If
End Set
End Property
'Private Function FilterDataRows(value As Object) As Boolean
' If TypeOf value Is DataRowView Then value = DirectCast(value, DataRowView).Row
' If Not TypeOf value Is DataRow Then Return False
' Dim dr = DirectCast(value, DataRow)
' If MatchMode = FilterViewFieldMode.SimpleMatch Then
' For Each field In Fields
' If InStr("" & dr(field), _filterText, CompareMethod.Text) > 0 Then Return True
' Next
' Return False
' Else
' For Each w In _filterTextValues
' Dim found = False
' For Each field In Fields
' If InStr("" & dr(field), w, CompareMethod.Text) > 0 Then
' If MatchMode = FilterViewFieldMode.OrSegments Then Return True
' found = True
' Exit For
' End If
' Next
' If MatchMode = FilterViewFieldMode.AndSegments AndAlso Not found Then Return False
' Next
' End If
' If MatchMode = FilterViewFieldMode.OrSegments Then Return False
' Return True
'End Function
'Private Function FilterListRows(value As Object) As Boolean
' If Not TypeOf value Is Data.List.Row Then Return False
' Dim rw = DirectCast(value, Data.List.Row)
' If MatchMode = FilterViewFieldMode.SimpleMatch Then
' Else
' For Each w In _filterTextValues
' Dim found = False
' For Each field In Fields
' If InStr("" & rw(field), w, CompareMethod.Text) > 0 Then
' If MatchMode = FilterViewFieldMode.OrSegments Then Return True
' found = True
' Exit For
' End If
' Next
' If MatchMode = FilterViewFieldMode.AndSegments AndAlso Not found Then Return False
' Next
' End If
' If MatchMode = FilterViewFieldMode.OrSegments Then Return False
' Return True
'End Function
'Private Function FilterObject(value As Object) As Boolean
' Dim found(Fields.Count - 1) As Boolean
' For i = 0 To Fields.Count - 1
' found(i) = False
' Next
' Dim f As Integer = -1
' For Each field In Fields
' f += 1
' Dim pi = value.GetType.GetProperty(field)
' Dim v = pi.GetValue(value) ' Minimize property retrieval cost
' For Each w In _values
' If Not found(f) And InStr("" & v, w, CompareMethod.Text) > 0 Then found(f) = True : Exit For
' Next
' Next
' For i = 0 To Fields.Count - 1
' If Not found(i) Then Return False
' Next
' Return True
'End Function
'Private Function FilterDictionary(value As Object) As Boolean
' If Not TypeOf value Is IDictionary Then Return False
' Dim dict = DirectCast(value, IDictionary)
' For Each w In _values
' Dim found = False
' For Each field In Fields
' If InStr("" & dict(field), w, CompareMethod.Text) > 0 Then found = True : Exit For
' Next
' If Not found Then Return False
' Next
' Return True
'End Function
'Private Function FilterExpandoObject(value As Object) As Boolean
' If Not TypeOf value Is System.Dynamic.ExpandoObject Then Return False
' Dim dict = DirectCast(value, IDictionary(Of String, Object))
' For Each w In _values
' Dim found = False
' For Each field In Fields
' If InStr("" & dict(field), w, CompareMethod.Text) > 0 Then found = True : Exit For
' Next
' If Not found Then Return False
' Next
' Return True
'End Function
'Private Function FilterDynamicObject(value As Object) As Boolean
' If Not TypeOf value Is Dynamic.DynamicObject Then Return False
' Dim dobj = DirectCast(value, Dynamic.DynamicObject)
' Dim found(Fields.Count - 1) As Boolean
' For i = 0 To Fields.Count - 1
' found(i) = False
' Next
' Dim f As Integer = -1
' For Each field In Fields
' f += 1
' Dim v = GetDynamicMember(dobj, field) ' Minimize field retrieval expense
' For Each w In _values
' If Not found(f) And InStr("" & v, w, CompareMethod.Text) > 0 Then found(f) = True : Exit For
' Next
' Next
' For i = 0 To Fields.Count - 1
' If Not found(i) Then Return False
' Next
' Return True
'End Function
Private Function FilterTestSimple(value As Object) As Boolean
If _filterText = String.Empty Then Return True
If _getValue Is Nothing Then Return True
For Each field In Fields
Try
If InStr(_getValue.Invoke(value, field), _filterText, CompareMethod.Text) > 0 Then Return True
Catch ex As Exception
Stop
End Try
Next
Return False
End Function
Private Function FilterTestAnd(value As Object) As Boolean
Dim foundCount As Integer = 0
If _filterText = String.Empty Then Return True
If _getValue Is Nothing Then Return True
Dim valueCount = _filterTextValues.Count
Dim found(valueCount - 1) As Boolean
For i = 0 To found.Length - 1
found(i) = False
Next
For Each field In Fields
Dim v As String = _getValue.Invoke(value, field) ' Minimize field retrieval expense
Dim f As Integer = -1
For Each w In _filterTextValues
f += 1
If Not found(f) AndAlso InStr(v, w, CompareMethod.Text) > 0 Then
found(f) = True
foundCount += 1
If foundCount = valueCount Then
Return True
End If
End If
Next
Next
Return (foundCount = valueCount)
End Function
Private Function FilterTestOr(value As Object) As Boolean
If _filterText = String.Empty Then Return True
If _getValue Is Nothing Then Return True
For Each field In Fields
Dim v As String = _getValue.Invoke(value, field) ' Minimize field retrieval expense
For Each w In _filterTextValues
If InStr(v, w, CompareMethod.Text) > 0 Then Return True
Next
Next
Return False
End Function
'Private Function FilterTest(value As Object) As Boolean
' If MatchMode = FilterViewFieldMode.SimpleMatch Then
' End If
' For Each field In Fields
' Dim found = False
' Dim v = getValue(value, field) ' Minimize field retrieval expense
' For Each w In _values
' If InStr(v, w, CompareMethod.Text) > 0 Then
' If MatchMode = FilterViewFieldMode.OrSegments Then Return True
' found = True
' End If
' If MatchMode = FilterViewFieldMode.AndSegments And Not found Then Return False
' Next
' Next
' If MatchMode = FilterViewFieldMode.OrSegments Then Return False
' Return True
'End Function
End Class
Public Enum FilterViewFieldMode
AndSegments
OrSegments
SimpleMatch
End Enum
End Namespace