HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Another DataGrid (ObservableCollection) Filtering Method

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
methodanotherdatagridobservablecollectionfiltering

Problem

I have re-written my DataGrid filtering method to try to improve performance and I feel that although this is the fastest yet, there is still room for improvement on some of the slower machines my program runs on.

The DataGrid is bound to an ObservableCollection, as the user enters text into my searchBox each CompanyModel that matches the filter is added into a filter ListBox. The ListBox is limited to the first 25 CompanyModels so as to enhance performance. Here is the method that is called as the user types;

private void FilterCompanies()
{
    FilteredCompanies = new ObservableCollection();
    FilteredCompanies.Clear();

    string searchText = CleanseText(searchBox.Text.ToLower());

    foreach (CompanyModel company in AllCompanies)
    {
        if (!string.IsNullOrEmpty(searchText))
        {
            if (FilteredCompanies.Count  0)
    {
        companiesListBox.ItemsSource = FilteredCompanies;
        companiesListBox.Visibility = Visibility.Visible;
    }
    else
    {
        companiesListBox.ItemsSource = null;
        companiesListBox.Visibility = Visibility.Collapsed;
    }
}


From the code you can see there are two more methods involved in the filtering;

CompanyMatchesFilters

```
private bool CompanyMatchesFilters(CompanyModel company)
{
foreach (FilterItem item in firstListBoxItems)
{
if (item.ID == 1 && company.CurrentStatus != 1)
{
return false;
}
if (item.ID == 2 && company.Subcontractor != 1)
{
return false;
}
if (item.ID == 3 && company.Supplier != 1)
{
return false;
}
if (item.ID == 4 && company.Planthire != 1)
{
return false;
}
if (item.ID == 5 && company.Architect != 1)
{
return false;
}
if (item.ID == 6 && company.QS != 1)
{
return false;
}
if (item.ID == 7 && company.ProjectManager

Solution

You can refactor this into LINQ query for (arguably) better readability.

AllCompanies.Where(c => CompanyMatchesFilters(c))
            .Where(c => CleanseText(company.Name).Contains(searchText)
                     || CleanseText(company.Town).Contains(searchText) 
                     || CleanseText(company.Postcode).Contains(searchText))
            .Take(25);


As for performance - nothing in the code you've shown strikes me as potential performance bottleneck. You will probably have to run a profiler to pinpoint it. One thing in particular you might want to look at is what triggers the search and how often it is executed. For example, if I enter 10 chars in search box, do I search 1 or 10 times? While the filtering logic looks fairly lightweight, the performance implications of recreating 25 item templates in UI on every keystroke can be severe (depending on how complex the DataTemplate is). Rx has some nice extensions that might help in throttling UI events.

P.S. Whats the point of removing all meaningful characters in CleanseText? What characters are you interested in then? This is extremely unclear, you should document that portion of your code.

Code Snippets

AllCompanies.Where(c => CompanyMatchesFilters(c))
            .Where(c => CleanseText(company.Name).Contains(searchText)
                     || CleanseText(company.Town).Contains(searchText) 
                     || CleanseText(company.Postcode).Contains(searchText))
            .Take(25);

Context

StackExchange Code Review Q#147414, answer score: 6

Revisions (0)

No revisions yet.