Slow Filtering Method on DataGrid Sometime ago I asked a question regarding a slow Filtering method for my DataGrid. Months later and I have a relatively quick method, though I am still looking to improve performance, especially when the user is deleting text from the SearchBox as this seems to slow down more than if the user is typing characters in.

OnTypingIntoSearchBox

private void OnSearchBoxTextChanged(object sender, TextChangedEventArgs e)
{
    ApplyFilter();
}


ApplyFilter

private void ApplyFilter()
{
    if (CurrentJobsCollectionView != null)
    {
        CurrentJobsCollectionView.Filter = FilterJobs;
    }
    UpdateJobCounter();
}


FilterJobs

    private bool FilterJobs(object o)
    {
        return FilterByCheckBox(o) &amp;&amp; FilterByJobsSearchBox(o);
    }


FilterByJobsSearchBox

private bool FilterByJobsSearchBox(object o)
{
    try
    {
        var searchText = CharactersOnly(jobsSearchBox.Text);
        var job = o as JobModel;
        if (searchText == string.Empty)
        {
            return true;
        }
        else
        {
            if (CompanyContains(job.JobReference, searchText.ToLower()) || 
                CompanyContains(job.CaseClient, searchText.ToLower()) || 
                CompanyContains(job.JobDescription, searchText.ToLower()) ||
                CompanyContains(job.JobNotes, searchText.ToLower()) ||
                CompanyContains(job.JobID.ToString(), searchText.ToLower()))
            {
                return true;
            }
        }
        return false;
    }
    catch (System.Exception ex)
    {
        var hEs = new HandleExceptionService();
        hEs.HandleException(ex.ToString());
        return false;
    }
}


FilterByCheckBox

private bool FilterByCheckBox(object o)
{
    var today = DateTime.Today;
    criteria.Clear();

    if (yourJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == yourJobsCheckBox.Tag.ToString()));
    }

    if (adamJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == adamJobsCheckBox.Tag.ToString()));
    }

    if (chrisJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == chrisJobsCheckBox.Tag.ToString()));
    }

    if (danJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == danJobsCheckBox.Tag.ToString()));
    }

    if (emilyJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == emilyJobsCheckBox.Tag.ToString()));
    }

    if (kitJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == kitJobsCheckBox.Tag.ToString()));
    }

    if (mattJobsCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == mattJobsCheckBox.Tag.ToString()));
    }

    if (unallocatedCheckBox.IsChecked == true)
    {
        criteria.Add(new Predicate&lt;JobModel&gt;(x =&gt; x.ITName == unallocatedCheckBox.Tag.ToString()));
    }

    if (_employees.Children.OfType&lt;CheckBox&gt;().All(c =&gt; Convert.ToBoolean(!c.IsChecked))) // If none are checked
    {
        currentJobsDataGrid.ItemsSource = null;
        completedJobsDataGrid.ItemsSource = null;
        archivedJobsDataGrid.ItemsSource = null;
    }

    JobModel job = o as JobModel;
    bool isIn = true;
    if (criteria.Count() == 0)
        return isIn;
    isIn = criteria.Any(x =&gt; x(job));
    return isIn;
}


I hope that isn't too much code - apologies if it is. I'm essentially looking for anyway to improve the efficiency of this filtering method, either by the user searching through typing in text or by checking specific checkboxes.
The end of your code... 


bool isIn = true;
if (criteria.Count() == 0)
    return isIn;
isIn = criteria.Any(x =&gt; x(job));
return isIn;



Looks really weird to me

Get rid of the boolean variable, you don't need it to return a true or false value from expressions that return a boolean.  

Also, make this an if/else statement.

if (criteria.Count() == 0)
{
    return true;
}
else
{
    return criteria.Any(x =&gt; x(job));
}


You could also condense this to a single return statement using a ternary statement

return criteria.Count() == 0 ? true : criteria.Any(x =&gt; x(job));


or even a simple or conditional

return criteria.Count() == 0 || criteria.Any(x =&gt; x(job));


some would say that having the ==0 isn't very clean when you could instead write it like this

return !criteria.Any() || critera.Any(x =&gt;  x(job));




On the other hand, in your FilterByJobsSearchBox method I would un-nest the if statement, it is indented in a way that isn't necessary and looks messy.

Something else that you should do to make this more dry, is to apply the ToLower method to the variable assignment instead of when you compare to see if the jobs contain the search text, I will show you what I mean


    var searchText = CharactersOnly(jobsSearchBox.Text);
    var job = o as JobModel;
    if (searchText == string.Empty)
    {
        return true;
    }
    else
    {
        if (CompanyContains(job.JobReference, searchText.ToLower()) || 
            CompanyContains(job.CaseClient, searchText.ToLower()) || 
            CompanyContains(job.JobDescription, searchText.ToLower()) ||
            CompanyContains(job.JobNotes, searchText.ToLower()) ||
            CompanyContains(job.JobID.ToString(), searchText.ToLower()))
        {
            return true;
        }
    }
    return false;



Here is what it looks like when you do everything I mentioned above

var searchText = CharactersOnly(jobsSearchBox.Text).ToLower();
var job = o as JobModel;
if (searchText == string.Empty)
{
    return true;
}

if (CompanyContains(job.JobReference, searchText) || 
    CompanyContains(job.CaseClient, searchText) || 
    CompanyContains(job.JobDescription, searchText) ||
    CompanyContains(job.JobNotes, searchText) ||
    CompanyContains(job.JobID.ToString(), searchText))
{
    return true;
}

return false;


we could go a little further and make this one return statement as well, it will be a very long return statement....

var searchText = CharactersOnly(jobsSearchBox.Text).ToLower();
var job = o as JobModel;
return searchText == string.Empty 
    || CompanyContains(job.JobReference, searchText)
    || CompanyContains(job.CaseClient, searchText)  
    || CompanyContains(job.JobDescription, searchText) 
    || CompanyContains(job.JobNotes, searchText) 
    || CompanyContains(job.JobID.ToString(), searchText);