简体   繁体   中英

Filtering a collection based on filtering rules

I have an observable collection of Entities, with each entity having a status added, deleted, modified and cancelled.

I have four buttons ( toggle ) when clicked should filter my collection as below:

  • If I select the button Added, then my collection should contain entities with status added.
  • If I select the button Deleted and Added, then my collection should contain entities with status Deleted AND entities with status Added, none of the rest.
  • If I select the button Deleted,Added and Modified, then my collection should contain entities with status Deleted, Added AND Modified. . . so on.
  • If I unselect one of the buttons, it should remove those entities from the collection with that status. For example if I unselect Deleted, but select Added and Modified, then my collection should contain items with Added and Modified status and NOT Deleted ones.

For implementing this I have created a master collection and a filtered collection. The Filter collection gets filtered based on the selections and unselections. The following is my code:

private bool _clickedAdded;
    public bool ClickedAdded
    {
        get { return _clickedAdded; }
        set
        {
            _clickedAdded = value;
            if(!_clickedAdded)
                FilterAny(typeof(Added));

        }
    }

    private bool _clickedDeleted;
    public bool ClickedDeleted
    {
        get { return _clickedDeleted; }
        set
        {
            _clickedDeleted = value;
            if (!_clickedDeleted)
                FilterAny(typeof(Deleted));
        }
    }

    private bool _clickedModified;
    public bool ClickedModified
    {
        get { return _clickedModified; }
        set
        {
            _clickedModified = value;
            if (!_clickedModified)
                FilterAny(typeof(Modified));
        }
    }

    private void FilterAny(Type status)
    {
        Func<Entity, bool> predicate = entity => entity.Status.GetType() != status;

        var filteredItems = MasterEntites.Where(predicate);
        FilteredEntities = new ObservableCollection<Entity>(filteredItems);
    }

This however breaks the above rules - for example if I have all selected, and then I remove Added followed by deleted then it still shows the list of Added, Modified and Cancelled. It should be just Modified and Cancelled in the filtered collection.

Can you please help me in solving this issue? Also do I need 2 different list to solve this. Please note that I'm using .NET 3.5.

You need the extension of Linq - http://www.albahari.com/nutshell/predicatebuilder.aspx This class provides PredicateBuilder which can create queries on the fly.

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }

  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

Then you make an OnClick handler for all these buttons and inside it you put the following code

  var predicate = PredicateBuilder.False<Entity>();

    if(ClickedAdded)
       predicate = predicate.Or(x=>x.Status == "Added");
    if(ClickedDeleted)
       predicate = predicate.Or(x=>x.Status == "Deleted");
    if(ClickedModified)
       predicate = predicate.Or(x=>x.Status == "Modified");

    return masterEntities.AsQueryable().Where(predicate);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM