If you find yourself binding your RadGridView to objects that are dynamically generated by Castle's DictionaryAdapter.
You might be surprised by the expressions that are generated by the ExpressionEditor involve a mysterious CastleDictionaryAdapterType like
Expression {Expression<System.Func<CastleDictionaryAdapterType,
bool
>>}
when you were expecting it to be:
Expression {Expression<System.Func<IDataRecord,
bool
>>}
where IDataRecord is the interface your run-time instances are generated from by DictionaryAdapter
Despite the fact that CastleDictionaryAdapterType implements your IDataRecord (and a bunch of other things) you won't be able to directly cast between them as your FilterDescriptor requires
The solution is to re-write the expression that ExpressionEditor.Expression property gives you. Here's a simple expression visitor that does that:
public
class
CastleDictionaryAdapterTypeVisitor<TInput> : ExpressionVisitor
{
private
ReadOnlyCollection<ParameterExpression> _parameters;
private
ParameterExpression _parameter;
public
Expression Modify(Expression expression_)
{
return
Visit(expression_);
}
#region Overrides of ExpressionVisitor
protected
override
Expression VisitParameter(ParameterExpression node_)
{
return
_parameter ?? (_parameter = Expression.Parameter(
typeof
(TInput), node_.Name));
}
protected
override
Expression VisitLambda<T>(Expression<T> node_)
{
_parameters = VisitAndConvert(node_.Parameters, node_.Name);
return
Expression.Lambda(Visit(node_.Body), _parameters);
}
protected
override
Expression VisitMember(MemberExpression node_)
{
return
node_.Member.DeclaringType?.ToString() ==
"CastleDictionaryAdapterType"
? Expression.Property(Visit(node_.Expression), node_.Member.Name) :
base
.VisitMember(node_);
}
#endregion
}
You can use it like this (I've modified the ExpressionEditor filtering RadGridView Telerik sample)
private
void
ExpressionEditor_OnExpressionChanged(
object
sender_, RadRoutedEventArgs e_)
{
if
(
this
.ExpressionEditor.Expression !=
null
&&
this
.ExpressionEditor.Expression.GetType().ToString().Contains(
"CastleDictionaryAdapterType"
))
{
var visitor =
new
CastleDictionaryAdapterTypeVisitor<ITestDataRecord>();
var convertedExpression = visitor.Modify(ExpressionEditor.Expression)
as
Expression<Func<ITestDataRecord,
bool
>>;
if
(convertedExpression !=
null
)
this
._genericFilterDescriptor.FilteringExpression = convertedExpression;
if
(!
this
.RadGridView.FilterDescriptors.Contains(
this
._genericFilterDescriptor))
this
.RadGridView.FilterDescriptors.Add(
this
._genericFilterDescriptor);
this
.errorMessageBlock.Visibility = Visibility.Collapsed;
}
else
if
(
this
.ExpressionEditor.Expression ==
null
)
{
if
(
this
.RadGridView.FilterDescriptors.Contains(
this
._genericFilterDescriptor))
this
.RadGridView.FilterDescriptors.Remove(
this
._genericFilterDescriptor);
this
.errorMessageBlock.Visibility = Visibility.Collapsed;
}
else
{
this
.errorMessageBlock.Visibility = Visibility.Visible;
}
}
What is needed here is to provide a way to signal to the ExpressionEditor the specific type/interface to use, as opposed to letting the control figure it out from its Item property.