Image by salendron | Some rights reserved
Need to create a wild-card style search method using LINQ? It is ridiculously easy.
Below is a simple example, using the .StartsWith
method from the string class. In an application for work, I needed a “Google-like” search performed on a list where with each keystroke, the list is filtered to more closely match what is typed into the search input box.
.At work I am stuck still using Windows Forms, so what you see below is used to populate the venerable Winforms Treeview. The filtering piece, though, can be useful in other situations.
I’m stepping away briefly from my examination of routing in ASP.NET MVC and ASP.NET Web API to toss this little gem out there. There’s nothing fancy or new here, but if you are new to LINQ, or just never had to use LINQ with a wild card search scenario before, this might be helpful.
Basic LINQ Query Using the .StartsWith Method
The wildcard search below will filter the IEnumerable<Company>
on the Company.CompanyName
property, as well as on the Company.CompanyCode
property (which represents the company instance’s US Tax ID number).
Basic Code for the Wildcard Search Using LINQ .StartsWith Method:
>public void LoadListView(IEnumerable<Company> companies, string searchString = "") { IEnumerable<Company> query; if (!(searchString.Length > 1)) { query = companies; } else { query = (from company in companies where company.CompanyName.StartsWith(searchString, StringComparison.OrdinalIgnoreCase) || company.CompanyCode.StartsWith(searchString, StringComparison.OrdinalIgnoreCase) orderby company.CompanyName select company); } foreach (var filteredCompany in query) { // Load the ListView control . . . } }
In the above, a source Enumerable is passed in and becomes the target for the filter. Additionally, an optional search string is passed, with an empty string as default. The way the method above is set up, if the search string is not at least one character in length, the entire contents of the source Enumerable are shown. Once the length of the input string is greater than a single character, the filter is applied.
The Search Function Before Typing in the Search Textbox:
As you can see, once we begin to type, and the input string ( in this case, “al” so far) length exceeds a single character, the filtering begins:
The Search Function After Typing in the Search Textbox:
Depending upon your needs, you might modify this to display nothing until an input string is present. Also, depending upon the size of your original data set, you might need to apply other strategies to winnow down the starting instance of IEnumerable passed in (in my case, the entire list of companies is supplied. We may have to look at that if it grows too large).
For Case-Insensitivity Use StringComparison.OrdinalIgnoreCase
By default, LINQ will perform a case-sensitive comparison. Not especially useful in this context. To tell LINQ to ignore case, I have provided a second parameter to the StartsWith
method, StringComparison.OrdinalIgnoreCase
.
LINQ filtering can also utilize the corresponding string
methods EndsWith
and Contains
which perform their respective functions in the manner implied by their names.
Additional Items of Interest:
- Extending C# Listview with Collapsible Groups (Part I)
- Extending C# Listview with Collapsible Groups (Part II)
- C#: A Better Date-Masked Text Box
- Visual Studio: Use Conditional Compilation to Control Runtime Settings for Different Deployment Scenarios
Comments
XIV-Admin
AuthorThis is just a simple Winforms Listview used in a project for work. The Winforms Listview does not support direct databinding, so far as I know. If this were a Combobox or List, you could do what you suggest, but for the Winforms Listview, I have always had to load them "manually." If you know differently, please, do tell!
Alan Placko
AuthorIs there a reason you are using a for loop to load the company names into the ListView? Are there times where binding is not supposed to be used?