Binding DynamicObject to a DataGrid with automatic column generation?

萝らか妹 提交于 2019-11-27 13:46:29

There is no uniform way to query dynamic properties, generally it's expected that you know them ahead of time. With DynamicObject, implementers may override GetMemberNames and that generally gives you the properties, however it is really meant for debugging because there is no requirement that it provide all properties. Otherwise if it's your own DynamicObject you just have to write your own method to get the properties based on your dynamic implementation. For example ExpandoObject lets you query all the properties using the IDictionary interface.

So once you have a way to get your properties you need to tell the DataGrid. Unfortunately with a DataGrid, the issue with implementing ICustomTypeDescriptor to tell the DataGrid about your properties is that DataGrid gets the TypeDescriptors using the Type not the instance, which is a problem for Dynamic objects, however implementing ITypedList on the collection of DynamicObjects will work with the very tiny gotcha of if you don't implement the non-generic IList interface on your collection, it will be stripped out before it gets to the point where it checks for ITypeList.

So in summary, Implement a Collection with ITypedList and IList. With ITypedList return null for GetListName and just implement GetItemProperties(PropertyDescriptor[] listAccessors); Ignore listAccessors and return a PropertyDescriptorCollection of PropertyDescriptors for each member named based on the best represented Dynamic object instance in your list (most likely just the first object). You do have to implement a subclass of PropertyDescriptor, an easy and general way to the Get/Set value is to use the opensource framework Dynamitey

using System;
using System.ComponentModel;
using Dynamitey;
public class DynamicPropertyDescriptor:PropertyDescriptor
{
        public DynamicPropertyDescriptor(string name) : base(name, null)
        {
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override object GetValue(object component)
        {
           return Dynamic.InvokeGet(component, Name);
        }

        public override void ResetValue(object component)
        {

        }

        public override void SetValue(object component, object value)
        {
            Dynamic.InvokeSet(component, Name, value);
        }

        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }

        public override Type ComponentType
        {
            get { return typeof(object); }
        }

        public override bool IsReadOnly
        {
            get { return false; }
        }

        public override Type PropertyType
        {
            get
            {
                return typeof (object);
            }
        }
}

I think the DataGrid uses TypeDescriptor to get the object properties to create the columns. So you should be able to achieve this if your DynamicObject implements ICustomTypeDescriptor. Implement the GetProperties method so that it returns the dynamic properties of your object.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!