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)
'BindModelInfo is a method that takes a SQLDataReader and creates a ModelInfo class to represent the data object for a Car Model
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)
' Search predicate returns true if a .MakeId = MakeId.
Private Shared Function ModelByMake(ByVal mi As ModelsInfo) _
If mi.MakeId = _MakeId Then
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
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.