3

I have a gridview which has drop down boxes in each header for filtering. Each filter is loaded with the distinct values from its column when loaded. At run time, I add "ALL" to allow the user to select all from that field. I am trying to build the linq statement dynamically to ignore the field if the drop down box is set to "ALL". Is this possible? I want to see if I can do this in one single statement. The example below only shows 2 dropdown boxes, but my actually case has up to 5.

If I choose to use if then statements, I end up with spaghetti code.

DropDownList drpOwners = this.grdOtherQuotes.HeaderRow.FindControl("drpOwners") as DropDownList;                     
DropDownList drpCompanyName = this.grdOtherQuotes.HeaderRow.FindControl("drpCompanyName") as DropDownList;

var filteredList = (from x in allQuotes
                          where (drpOwners.SelectedValue != ALL) ? x.SalesRepFullName == drpOwners.SelectedValue:true                                    
                                && drpCompanyName.SelectedValue != ALL ? x.CompanyName == drpCompanyName.SelectedValue: true
                          select x);
1

3 Answers 3

10

Personally, I'd find having this broken up to be simpler:

IEnumerable<Quote> filteredList = allQuotes;
// If using EF or LINQ to SQL, use: IQueryable<Quote> filteredList = allQuotes;
if (drpOwners.SelectedValue != ALL) 
   filteredList = filteredList.Where(x => x.SalesRepFullName == drpOwners.SelectedValue);
if (drpCompanyName.SelectedValue != ALL) 
   filteredList = filteredList.Where(x => x.CompanyName == drpCompanyName.SelectedValue);
// More conditions as needed

This really isn't any longer, and it's far simpler to follow.


If you really wanted to be able to write this as a "one-liner", you could make an extension method to build the query. For example, if using Entity Framework:

static IQueryable<T> AddCondition(this IQueryable<T> queryable, Func<bool> predicate, Expression<Func<T,bool>> filter)
{
     if (predicate())
         return queryable.Where(filter);
     else
         return queryable;
}

This would then let you write this as:

var filteredList = allQuotes
                     .AddCondition(() => drpOwners.SelectedValue != ALL, x => x.SalesRepFullName == drpOwners.SelectedValue)
                     .AddCondition(() => drpCompanyName.SelectedValue != ALL, x.CompanyName == drpCompanyName.SelectedValue);

You could, of course, take this even further, and make a version that hard-wires the predicate to check a combo box against "ALL", making the predicate shorter (just the combo box).

4
  • It is based on the fact that IQueryable is returned, hence the where clauses are not executed until the data is actually needed. +1
    – ΩmegaMan
    Commented Oct 16, 2012 at 16:47
  • @OmegaMan The OP wasn't clear whether "allQuotes" is IEnumerable<T> or IQueryable<T> - however, this will actually work with EF, where the original probably will not (I don't think the conditional operators in this case, where "where true", will map through with EF) Commented Oct 16, 2012 at 16:48
  • @ReedCopsey - Your code will cause the query to execute because you're using Func<T, bool>. It should be Expression<Func<t,bool>> Commented Oct 16, 2012 at 17:05
  • @MystereMan Yeah, fixed - I originally wrote thinking LINQ to Objects, then changed at last minute, and forgot to fixed - taken care of now. Commented Oct 16, 2012 at 17:10
1

You could create a helper method that handles the All logic. Something like:

private bool CompareSelectedValue(string value, string dropDownValue)
{
  if(dropDownValue == "ALL")
    return true;
  else
    return value == dropDownValue;
}

Then your query could be:

var filteredList = (from x in allQuotes
                          where (CompareSelectedValue(x.SalesRepFullName, drpOwners.SelectedValue)                                    
                                && CompareSelectedValue(x.CompanyName, drpCompanyName.SelectedValue)
                          select x);
0

Create extension method(s) which encapsulate the where logic so it looks cleaner:

var filteredList = allQuotes.WhereDropOwnersAreContained()
                            .WhereCompanyIsContained()
                            ...
                            ;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.