Reputation: 95
I have a filter politique throughout the application that use EntityFramework and winform, now i need to design a class to facilitate the filtering, like that
public class TextPredicatFilter<T>
{
List<T> _list;
List<CheckedPredicat> _listPredicat= new List<CheckedPredicat>();
bool _active = true;
public TextPredicatFilter(BindingSource bs ,TextBox txtFilter, List<T> bindingList)
{
_list = bindingList;
txtFilter.TextChanged += delegate
{
if (!_active)
return;
foreach(CheckedPredicat prd in _listPredicat)
{
if(prd.CheckControl.Checked)
{
bs.DataSource = new BindingList<T>(_list.Where(t=>t.GetType().GetProperty(prd.ColumnName).GetConstantValue().ToString() == txtFilter.Text).ToList<T>());
}
}
};
}
public void Add(CheckedPredicat chkPredicat)
{
_listPredicat.Add(chkPredicat);
}}
public class CheckedPredicat
{
public RadioButton CheckControl { get; set; }
public string ColumnName { get; set; }
public bool UseLike { get; set; }
}
but this does't work! any idea?
Upvotes: 1
Views: 147
Reputation: 21470
You might want to check out Dynamic Linq, which lets you write filters like this;
using System.Linq.Dynamic; //Import the Dynamic LINQ library
var result = myQuery
.Where("Field1=\"SomeValue\"")
.Select("new (Field1, Field2)");
I think you can write the startswith/endswith direct in the WHERE clause; something like
var result = myQuery
.Where("Field1.StartsWith(\"somevalue\") || Field1.EndsWith(\"somevalue\")")
but I'm not sure.
Upvotes: 1
Reputation: 109079
First, make this independent of any UI implementation. You don't need BindingSources or RadioButtons to build a dynamic database query. Use the original data, filter them, and then re-bind the result to whichever UI framework you happen to use today... or tomorrow.
Secondly, keep it simple. All you need is a collection of column names, their search terms and booleans. You're only filtering. That doesn't require a whole new class TextPredicatFilter
doing the work.
Thirdly, to answer your question, use Dynamic LINQ to build the query. (Also recommended by Steve while I was preparing this).
Let's say you have this class:
public class Predicate
{
public string ColumnName { get; set; }
public string FilterValue { get; set; }
public bool UseLike { get; set; }
}
Then all the code to build the query could look like this:
using System.Linq.Dynamic;
IQueryable<Company> companies = context.Companies;
var predicates = new Predicate[]
{
new Predicate { ColumnName = "Name", FilterValue = "o", UseLike = true },
new Predicate { ColumnName = "Code", FilterValue = "c", UseLike = false },
};
foreach (var pred in predicates)
{
var predicateString = pred.UseLike
? "{0}.Contains(@{1})"
: "{0} = @{1}";
companies = companies
.Where(string.Format(predicateString, pred.ColumnName, 0), pred.FilterValue);
}
Now you can bind companies
(probably with ToList()
) to a BindingList or whatever type of display you want to use.
Upvotes: 2