How to Filter a Generic List
Generics are a great new feature of .NET 2.0 that still has some enough mystery that not many are actually leveraging this great new set of collection classes. Real quick, Generics are a templated set of collection classes that are a little thinner than a CollectionBase and a little more powerful than and ArrayList. One of my first cautions was how do you filter a generic. The solution I found was the use of the FindAll method, but I think it is a little clunky, and I think the same is true for sorting, but more on that later.
List is the core Generic Class and is in the format of List(Of Object). The List class has several included methods, several handle the filtering and sorting functionality, in this example I will demonstrate FindAll.
I am going to create a list of Car Makes and Models from my database.
'**** NOTE THIS EXAMPLE USES Extreme Web Works Core Data Acess Framework ****
Public Function GetModelList() As List(Of ModelsInfo)
Dim dr As SqlDataReader = ExecuteReader("spGetModelss")
Dim ml As New List(Of ModelsInfo)
While dr.Read
'BindModelInfo is a method that takes a SQLDataReader and creates a ModelInfo class to represent the data object for a Car Model
ml.Add(BindModelsInfo(dr))
End While
dr.Close()
Return ml
End Function
Once you have your list then you need to define a Delegate Method that will be used to filter your objects in the list. This method needs to be in either the class that will be manipulating your list or a wrapper class that will handle the functionality of your Generic List.
Public Class ModelList
Public ml As List(Of ModelsInfo)
Private Shared _MakeId As String = String.empty
Public Function GetModelsByMake(ByVal MakeId As String) As List(Of ModelsInfo)
'Since we can not pass the Makeid in the method we need to set the class variable
_MakeId = MakeId
Return ml.FindAll(AddressOf ModelByMake)
End Function
' Search predicate returns true if a .MakeId = MakeId.
Private Shared Function ModelByMake(ByVal mi As ModelsInfo) _
As Boolean
If mi.MakeId = _MakeId Then
Return True
Else
Return False
End If
End Function
End Class
Notice that I defined a shared member, MakeId to hold the MakeId that we will be filtering. First I had to make it shared because the delgate method 'ModelByMake' is a shared method. ModelByMake is a shared function that returns a Boolean, meaning that the Object, ModelsInfo, meets our criteria, Make in this case. This method calls the List or models we set in our ModelList class. You need to think of the ModelList as a class that offers the extended functionality of the List class we are using.
The List class method FindAll has one parameter, a delegate method that will perform the filtering and return a Boolean Value. The delegate method takes one parameter, the Object class that your List is composed. The FindAll method passes each one of the Objects (ModelsInfo in our example) and will add the ones that meet our criteria to the List that is returned.
So if we want to define a method to bind all the Dodge models to a GridView it would look like this:
public sub BindDodges
Dim mc As New ModelsController
Dim ml As List(Of ModelsInfo) = mc.GetModelList
Dim mlc As New ModelList
mlc.ml = ml
Dim ml2 As List(Of ModelsInfo) = mlc.GetModelsByMake("DODGE")
GridView1.DataSource = ml2
GridView1.DataBind()
end sub
Of course you can set this up to pass Makes as a variable to the BindMethod and open it to more flexibility, so that is your homework assignment.