sroes
sroes

Reputation: 15053

Extending a Kendo Grid model with custom properties

Some of my models have custom (user managed) properties. Since they are dynamic I can't include them as properties in my model. So I tried providing the propeties using DynamicObject:

public class MyModel : DynamicObject
{
    public Dictionary<String, Object> CustomFields { get; set; }

    ...

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (binder.Name.StartWith("CustomField_"))
        {
            // get the custom field
        }
        return base.TryGetMember(binder, out result);
    }
}

Now using Kendo.Mvc.UI.Fluent.GridBuilder I'm building my custom attributes like this:

@(Html.Kendo().Grid<object>()
    .Columns(columns =>
    {
        ...
        foreach (var fieldDef in CustomFieldDefinitions)
        {
            var columnBuilder = columns.Bound("CustomField_" + fieldDef.Name);
            columnBuilder.Title(fieldDef.Name);
        }
    })
    ...

The extra columns are shown in the grid, but TryGetMember is never called.

I also tried implementing GetDynamicMemberNames. No difference.

Is there any way I can achieve this using an IDynamicMetaObjectProvider implementation (DynamicObject)?

Upvotes: 1

Views: 1172

Answers (1)

sroes
sroes

Reputation: 15053

Okay, I figured out what went wrong. I was using ajax binding, and in my controller I was basically doing the following:

[HttpPost]
public ActionResult GetRows([DataSourceRequest]DataSourceRequest request)
{
    return Json(GetRows<MyModel>().ToDataSourceResult(request, o => o));
}

Which means it was serializing my models which results in a list of objects that did not include my dynamic members.

I fixed it by mapping all the object members (including the dynamic) into a dictionary:

[HttpPost]
public ActionResult GetRows([DataSourceRequest]DataSourceRequest r)
{
    return Json(GetRows<MyModel>().ToDataSourceResult(r, ObjectToDictionary));
}

private Dictionary<String, Object> ObjectToDictionary(Object obj)
{
    return Dynamic.GetMemberNames(obj)
        .ToDictionary(name => name, name => Dynamic.InvokeGet(obj, name));
}

(Dyanmic comes from the class library https://github.com/ekonbenefits/dynamitey)

Upvotes: 1

Related Questions