I am using the CustomFilterDescriptor in your "RadControls for Silverlight Demos" and I would like to improve its functionalities.
I would like to this :
- "A + B" : Filtering data that contain A AND B
- "A || B" : Filterting data that contain A OR B
- "MyColum : A ": Filtering that on "MyColumn" which contains A
...
I could not find in where I can customize the linq expression.
Thank you for your help,
S
6 Answers, 1 is accepted
In this help article you may find additional information about the functionality of CustomFilterDescriptor. There is an information on how to filter with 'AND', 'OR' or 'Contains'.
I am not sure that I completely understand what you mean by: "I could not find in where I can customize the linq expression". May you please clarify how you would like to customize it?
Didie
the Telerik team

I have an issue with the FilterOperator.DoesNotContain. It does not Filter correctly...
Sample :
MyDataSource :
item1
item2
item3
1. MyFirstFilterSampleValue : =item1 ( => FilterOperator.Contains : must return item1 only)
Return : item1 (it works)
1. MySecondFilterSampleValue : !=item1 ( => FilterOperator.DoesNotContains: must return item2 & item3 only)
Return : item1, item2, item3 (it does nott work)
Here is my CustomFilterDescriptor :
public
class
CustomFilterDescriptor : FilterDescriptorBase
{
private
readonly
CompositeFilterDescriptor compositeFilterDesriptor;
private
static
readonly
ConstantExpression TrueExpression = System.Linq.Expressions.Expression.Constant(
true
);
IEnumerable<GridViewDataColumn> columns;
private
string
filterValue;
public
CustomFilterDescriptor(IEnumerable<GridViewDataColumn> columns)
{
this
.columns = columns;
this
.compositeFilterDesriptor =
new
CompositeFilterDescriptor();
this
.compositeFilterDesriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
foreach
(GridViewDataColumn column
in
columns)
{
this
.compositeFilterDesriptor.FilterDescriptors.Add(
this
.CreateFilterForColumn(column));
}
}
public
string
FilterValue
{
get
{
return
this
.filterValue;
}
set
{
if
(
this
.filterValue != value)
{
this
.filterValue = value;
this
.UpdateCompositeFilterValues();
this
.OnPropertyChanged(
"FilterValue"
);
}
}
}
protected
override
System.Linq.Expressions.Expression CreateFilterExpression(ParameterExpression parameterExpression)
{
if
(
string
.IsNullOrEmpty(
this
.FilterValue))
{
return
TrueExpression;
}
try
{
return
this
.compositeFilterDesriptor.CreateFilterExpression(parameterExpression);
}
catch
{
}
return
TrueExpression;
}
private
IFilterDescriptor CreateFilterForColumn(GridViewDataColumn column)
{
FilterOperator filterOperator = GetFilterOperatorForType(column.DataType);
FilterDescriptor descriptor =
new
FilterDescriptor(column.UniqueName, filterOperator,
this
.filterValue);
descriptor.MemberType = column.DataType;
return
descriptor;
}
private
FilterOperator GetFilterOperatorForType(Type dataType)
{
FilterOperator filterOperator = FilterOperator.Contains;
if
(!String.IsNullOrEmpty(filterValue))
{
if
(filterValue.StartsWith(
"!="
))
return
FilterOperator.IsNotEqualTo;
if
(filterValue.StartsWith(
"!"
))
return
FilterOperator.DoesNotContain;
if
(filterValue.StartsWith(
"="
))
return
FilterOperator.IsEqualTo;
if
(filterValue.StartsWith(
">"
))
return
FilterOperator.IsGreaterThan;
}
return
dataType ==
typeof
(
string
) ? FilterOperator.Contains : FilterOperator.IsEqualTo;
}
private
void
UpdateCompositeFilterValues()
{
if
(!String.IsNullOrEmpty(
this
.FilterValue))
{
this
.compositeFilterDesriptor.FilterDescriptors.Clear();
foreach
(GridViewDataColumn column
in
columns)
{
this
.compositeFilterDesriptor.FilterDescriptors.Add(
this
.CreateFilterForColumn(column));
}
foreach
(FilterDescriptor descriptor
in
this
.compositeFilterDesriptor.FilterDescriptors)
{
object
convertedValue = DefaultValue(descriptor.MemberType);
try
{
if
(descriptor.Value ==
null
)
descriptor.Value = FilterDescriptor.UnsetValue;
if
(descriptor.MemberType ==
null
)
descriptor.MemberType =
typeof
(
object
);
if
(descriptor.Operator== FilterOperator.IsNotEqualTo)
convertedValue = Convert.ChangeType(
this
.FilterValue.Remove(0, 2), descriptor.MemberType, CultureInfo.CurrentCulture);
else
if
(descriptor.Operator != FilterOperator.Contains || descriptor.Operator != FilterOperator.IsEqualTo)
convertedValue = Convert.ChangeType(
this
.FilterValue.Remove(0,1), descriptor.MemberType, CultureInfo.CurrentCulture);
else
convertedValue = Convert.ChangeType(
this
.FilterValue, descriptor.MemberType, CultureInfo.CurrentCulture);
}
catch
{
}
if
(descriptor.MemberType.IsAssignableFrom(
typeof
(DateTime)))
{
DateTime date;
if
(DateTime.TryParse(
this
.FilterValue,
out
date))
{
convertedValue = date;
}
}
descriptor.Value = convertedValue;
}
}
}
private
static
object
DefaultValue(Type type)
{
if
(type !=
null
&& type.IsValueType)
{
return
Activator.CreateInstance(type);
}
return
null
;
}
}
Regards,
S
Let me explain what we do when it comes to filtering.
Nothing that special.
We create a LINQ Expression based on the filter descriptors supplied. For the DoesNotContain filter operator we will create an expression that calls the String.Contains method and places "!" in front. So in fact, it is not us that filter that data but the .NET Framework. So, in pseudo code it will become something like this:
personCollection.Where(person => !person.LastName.Contains("John"))
It is not us that do the filtering -- it is the .NET Framework. So I can assure you that it is working correctly.
The DoesNotContain operator definitely works and you can see that in the default filtering UI of RadGridView on all of our on-line demos. Choose an arbitrary string column and test the DoesNotContain operator there. You will find out that it works correctly. Contains and DoesNotContain can be applied to strings only for the reasons I described above.
Most probably the problem comes from the fact that you have implemented your own custom filter descriptor, which I cannot take responsibility for. Please, check your implementation and whether it produces the correct LINQ expression. This lambda will be compiled and invoked to filter the data, so you can use your debugger to see what expression is your custom descriptor producing and where is the problem.
In case you think that you have found a bug with the default filtering of RadGridView, please send us a small sample project that does not involve custom descriptors and we will take a look at it.
Thank you for your understanding.
Ross
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
I think I know what the problem is. It is because of the OR operator when you use DoesNotContain. For Contains OR might be fine, but when you have DoesNotContain everything is inverted. Let me give you an example:
Person.FirstName.Contains("John") OR Person.LastName.Contains("John")
will return all people that are called John or Johnson, i.e. that have the string John somewhere in the name.
Now let us invert this:
Person.FirstName.DoesNotContain("John") OR Person.LastName.DoesNotContain("John")
will basically return all people because of the OR thing.
So everything works correctly, but your boolean logic is wrong.
You can see what expression is generated before it is returned from the method CreateFilterExpression.
See it with the debugger to see what is there and why.
I hope this helps.
Ross
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

+ [System.Linq.Expressions.LogicalBinaryExpression] {(((((IIF((item !=
null
), item.Name,
null
) ??
""
).ToLower() !=
"NY "
.ToLower()) OrElse ((IIF((item !=
null
), item.UserLogin,
null
) ??
""
).ToLower() !=
"NY "
.ToLower())) OrElse ((IIF((item !=
null
), item.Group,
null
) ??
""
).ToLower() !=
"NY "
.ToLower())) OrElse (Convert(item) != Convert(
"NY "
)))} System.Linq.Expressions.LogicalBinaryExpression
I need to replace the OrElse by And... but I am not allowed to access CreateFilterExpression.
If I create my own CreateFilterExpression method and return and Expression should it work?
regards,
S
No, you should simply change the LogicalOperator of the CompositeFilterDescriptior from OR to AND and the resulting expression will be with AND's instead of with OR's.
See, you are doing this yourself in the beginning:
this
.compositeFilterDesriptor.LogicalOperator = FilterCompositionLogicalOperator.Or;
When the user chooses DoesNotContain, you can change the operator to FilterCompositionLogicalOperator.And; and the resulting LINQ expression will be with AND's.
I hope this helps.
Ross
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!