Reputation: 1763
At the moment I get the number of possible combinations (Factorial of the number of check-boxes) and write that many if statements, something like:
Assuming I have 3 check-boxes:
if (IncludeIncomingCalls && !IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && !x.OutgoingCall && !x.ExternalCall);
}
if (!IncludeIncomingCalls && IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && x.OutgoingCall && !x.ExternalCall);
}
if (!IncludeIncomingCalls && !IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && !x.OutgoingCall && x.ExternalCall);
}
if (IncludeIncomingCalls && IncludeOutgoingCalls && !IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && x.OutgoingCall && !x.ExternalCall);
}
if (IncludeIncomingCalls && !IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => x.IncomingCall && !x.OutgoingCall && x.ExternalCall);
}
if (!IncludeIncomingCalls && IncludeOutgoingCalls && IncludeExternalCalls)
{
return _callsData.Where(x => !x.IncomingCall && x.OutgoingCall && x.ExternalCall);
}
Even though this will meet the requirement I don't see it as an optimal solution considering that the number of check-boxes might increase in the future and the number of the combinations could get massive.
I was wandering if there is a known pattern when it comes to filtering lists based on selected check-boxes?
Upvotes: 0
Views: 74
Reputation: 32740
You could use the following pattern:
//some checkboxes
CheckBox chkA = ...
CheckBox chkB = ...
CheckBox chkC = ...
//build up your filters
var filters = new List<Predicate<SomeEntity>>();
filters.Add(e => chkA.Checked && e.IsA);
filters.Add(e => chkB.Checked && e.IsB);
filters.Add(e => chkC.Checked && e.IsC);
//And now simply apply the filters
var entities = ... //some enumerable of SomeEntity
var filteredEntities = entities.Where(e => filters.All(filter => filter(e)));
Note that this will only work correctly if IsA
, IsB
and IsC
are excluding conditions, but this seems to be the set up you currently have.
Upvotes: 0
Reputation: 9463
Note that you can compose the IQueryable
. You can add additional Where
clauses as needed.
var result = callsData.Select(x => x);
if (IncludeIncomingCalls) {
result = result.Where(x => x.IncomingCall);
}
else {
result = result.Where(x => !x.IncomingCall);
}
if (IncludeOutgoingCalls) {
result = result.Where(x => x.OutgoingCall);
}
else {
result = result.Where(x => !x.OutgoingCall);
}
if (IncludeExternalCalls) {
result = result.Where(x => x.ExternalCall);
}
else {
result = result.Where(x => !x.ExternalCall);
}
return result;
I just show this as a general pattern. For your usecase, the solution of Ubiquitous Developers is easier to read and understand.
But if the condition is more complex than just a bit flag, this pattern might come in handy. Just as an example:
if (ShowOnlyActive) {
result = result.Where(x => x.State == CallState.Active);
}
else {
result = result.Where(x => x.State == CallState.Deleted || x.State == CallState.Inactive);
}
Off topic, just to further illustrate this general concept: adding additional clauses to an IQueryable
can be used to refactor parts of a query to helper or extension methods, for example to implement paging.
public interface IPageableQuery {
// The page size (i.e. the number of elements to be displayed).
// The method processing the Query will Take() this number of elements.
int DisplayLength { get; set; }
// The number of elements that have already been displayed.
// The method processing the Query will Skip() over these elements.
int DisplayStart { get; set; }
}
public static IQueryable<T> ApplyPaging<T>(this IQueryable<T> entries, IPageableQuery query)
where T : class {
if (query.DisplayStart >= 0 && query.DisplayLength > 0) {
return entries.Skip(query.DisplayStart).Take(query.DisplayLength);
}
return entries;
}
Upvotes: 0
Reputation: 59
Try this :
return _callsData.Where(x => x.IncomingCall==IncludeIncomingCalls && x.OutgoingCall==IncludeOutgoingCalls && x.ExternalCall==IncludeExternalCalls);
Upvotes: 0
Reputation: 3717
Compare the Boolean value with each field.
Try this:
return _callsData.Where(x => x.IncomingCall == IncludeIncomingCalls && x.OutgoingCall == IncludeOutgoingCalls && x.ExternalCall== IncludeExternalCalls);
Upvotes: 1