Bind to "normal" properties in dynamic object

6 posts, 0 answers
  1. Alexander
    Alexander avatar
    78 posts
    Member since:
    Apr 2013

    Posted 16 Jan 2015 Link to this post

    Hi,

    we want to bind a RadGridView to a collection of objects that implement DynamicObject. However, we don't want to bind to the dynamic properties, but only classical properties (e.g. the Name property in the following example).

    public class MyDynamicObject : DynamicObject
    {
        public string Name { get; set; }
     
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return base.TryGetMember(binder, out result);
        }
     
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            return base.TrySetMember(binder, value);
        }
    }

    However, the RadGridView only tries to bind to the dynamic members and throws exceptions if the dynamic member is not found. It does not even check if there is a normal property with the same name. This affects not only binding, but also sorting, grouping and filtering.
    The typical behavior in WPF (e.g. when using a binding) and C# (when using the dynamic keyword) is to check for normal properties first! This should be the same in the RadGridView.

    Alex
  2. Ivan Ivanov
    Admin
    Ivan Ivanov avatar
    1217 posts

    Posted 19 Jan 2015 Link to this post

    Hi,

    We have a help article that illustrates certain modifications for the DynamicObject implementation that are needed in such scenarios: Have mixed CLR and DLR properties. Can you please have a look at it and tell us whether this approach works for you?

    Regards,
    Ivan Ivanov
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Alexander
    Alexander avatar
    78 posts
    Member since:
    Apr 2013

    Posted 19 Jan 2015 Link to this post

    Hello Ivan,
    thanks for your answer.

    I have to admit that I absolutely do not like this solution (even though it would be possible), as this simply is boilerplate code and I loose type safety and the possibility of simply renaming these properties. Is there a reason why you don't follow the typical behavior of C# and WPF?

    Alex
  4. Ivan Ivanov
    Admin
    Ivan Ivanov avatar
    1217 posts

    Posted 21 Jan 2015 Link to this post

    Hello,

    In order to achieve better performance we use the data binding mechanism only as last available option, as it is quite slow. Basically, we use the .Net expression API to retrieve property values, building member access lambda functions. However, we have separate logic for CLR and DLR properties, so the things need to be tweaked a little, if one wants to combine them. 

    Regards,
    Ivan Ivanov
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Alexander
    Alexander avatar
    78 posts
    Member since:
    Apr 2013

    Posted 23 Jan 2015 in reply to Ivan Ivanov Link to this post

    Yes, I debugged into your source code and saw that you use some Expression builder:


    if (elementType.IsDynamic())
    {
        return new DynamicPropertyAccessExpressionBuilder(elementType, memberName, memberType);
    }
    return new PropertyAccessExpressionBuilder(elementType, memberName, memberType);

    At the moment, I find it somewhat inconsistent that when you select "AutoGenerateColumns", the columns for both CLR and DLR properties are generated, however only DLR properties are considered to get the value. Particularly, GetDynamicMemberNames does not enumnerate the CLR properties - why do you rely that these will be handled by TryGetMember?

    My proposal points into the direction that your DynamicPropertyAccessExpressionBuilder should check if there is a CLR property with the given name and fall back to the normal property access before building the pure dynamic expression. Unfortunately, there does not seem to be a way to hook into this mechanism from user side. It would be nice if this could be improved on your side. If you don't want to break existing code, then maybe this could be guarded by some setting?

    Alex
  6. Ivan Ivanov
    Admin
    Ivan Ivanov avatar
    1217 posts

    Posted 24 Jan 2015 Link to this post

    Hi,

    You are right. This check can be done in accordance to the member specificity (CLR or DLR), instead of the declaration type. And this matter is closely related to your question about GetDynamicMemberNames and CLR properties. Actually, we create different PropertyDescriptors for the CLR and DLR properties, and on this level we can easily distinct them from each other. DynamicPropertyDescriptors are created for each member that GetDynamicMemberNames returns and CLR descriptors are retrieved afterwards.
    if (elementType.IsDynamicMetaObjectProvider())
    {
        descriptors.AddRange(GetPropertyDescriptorsForDynamicType(collectionView));
    }
     
    descriptors.AddRange(TypeDescriptor.GetProperties(elementType).OfType<PropertyDescriptor>());

    But deeper in the data engine, the expression builder in particular, we do not work with the descriptors themselves, but only with member names and member types. Thus this distinctive difference gets lost. The problem here lies in the fact that our expression builder engine has been written before we added DLR support. We can certainly improve this by providing this information to the expression builder, but this might not be a trivial change as it may affect the core functionality of several of our controls. Thank you for providing your feedback on this topic. We will consider it for a future improvement of our data engine.

    Regards,
    Ivan Ivanov
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top