Binding DynamicObject to a DataGrid with automatic column generation?
Asked Answered
P

2

12

I'm still experimenting with DynamicObjects. Now I need some information: I'm trying to bind an object inheriting from DynamicObject to a WPF DataGrid (not Silverlight).

How do I get the DataGrid to automatically create its columns from the available public properties of the object that are typically generated at runtime? Is that possible actually?

Pisano answered 18/3, 2010 at 22:19 Comment(0)
M
13

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);
            }
        }
}
Mars answered 14/3, 2011 at 13:39 Comment(1)
this works in winforms as well. Thank you very much!Elisabeth
L
2

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.

Lem answered 20/8, 2010 at 1:37 Comment(1)
This is the way to go with Silverlight in any case, as SL doesn't have ITypedList.Phelips

© 2022 - 2024 — McMap. All rights reserved.