Reputation: 3284
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:
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.
Upvotes: 1
Views: 797
Reputation: 743
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);
Upvotes: 2