using ExpressionEditor with Castle DictionaryAdpter

2 posts, 0 answers
  1. Erhan
    Erhan avatar
    2 posts
    Member since:
    Oct 2006

    Posted 29 Sep Link to this post

    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.

     

     

     

     

     

  2. Martin Vatev
    Admin
    Martin Vatev avatar
    90 posts

    Posted 04 Oct Link to this post

    Hello Erhan,

    Thank you for sharing your solution with the community. We appreciate it. For that reason, I have updated your Telerik points as a gratitude for your cooperation. 

    Regards,
    Martin Vatev
    Telerik by Progress
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  3. UI for WPF is Visual Studio 2017 Ready
Back to Top