12
\$\begingroup\$

I want to the user to filter a list of receipts by various criteria. Just the regular, an empty filter should show all items, an entry in customer should show all receipts from that customer and an additional entry in date should show all entries from said customer on the given date. I have the feeling, my if else apprach is not the best way, since with 4 criteria I'm already at 16 branches, not speak of 5, 6, or 7 criteria.

What is the most elegant way to achieve this.

Model:

class customer
{

    public int ID { get; set; }

    public string Name { get; set; }

}

class receipt
{

    public int ID { get; set; }

    public string Number { get; set; }

    public DateTime Date { get; set; }

    public double Amount { get; set; }

    public customer Customer { get; set; }

}

Viewmodel

class receiptViewModel
{

    ObservableCollection<receipt> ReceiptList { get; set; }

    List<receipt> ReceiptListView { get; set; }

    private string filter;

    public string Filter
    {
        get { return filter; }
        set
        {

            filter = value;

            if (number != null && date == null && customer && null)
            {
                ReceiptListView = ReceiptList.Where(x => x.Number.Contains(number)).ToList();
            }
            else if (number != null && date != null && customer && null)
            {
                ReceiptListView = ReceiptList.Where(x => x.Number.Contains(number) && x.Date === date).ToList();
            }
            //aso aso aso
          }
    }
\$\endgroup\$

1 Answer 1

13
\$\begingroup\$

You can build the LINQ query in several steps by appending new where clauses

IEnumerable<receipt> query = ReceiptList;
if (customer != null) {
    query = query.Where(x => x.CustomerId == customer.ID);
}
if (number != null) {
    query = query.Where(x => x.Number.Contains(number));
}
if (date != null) {
    query = query.Where(x => x.Date == date);
}
...
ReceiptListView = query.ToList();

This reduces the complexity from O(2ⁿ) to O(n)

\$\endgroup\$
1
  • 2
    \$\begingroup\$ It's probably also worth to look into linqkit's predicatebuilder if more complex predicates have to be put together (say instead of combining all the limitations, wanting "or"). \$\endgroup\$
    – Voo
    Commented Dec 26, 2018 at 0:00

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.