Binding a GridView to a Dynamic or ExpandoObject object
Asked Answered
L

7

18

I'm using Rob Conery's Massive ORM, and I haven't been able to bind the resulting ExpandoObject to a GridView.

I did find another Stackoverflow question that suggests using a framework called impromptu, but I'm not sure if that would work for this. If you know it does, please provide a code sample to actually convert an ExpandoObject to something that the GridView control can bind to.

Worst case scenario, has anyone implemented an additional method (that can be shared) for Massive to convert the resulting ExpandoObject to a POCO?

any help is greatly appreciated. Thanks.

Lockup answered 6/4, 2011 at 22:44 Comment(1)
see my answer on this thread that could put you on the right way : How to create in C# WPF a DataGrid dynamic columns binded to an observable collection of dynamic properties types at runtimeKeyser
B
52

Since you can't bind to an ExpandoObject, you can convert the data into a DataTable. This extension method will do that for you. I might submit this for inclusion to Massive.

/// <summary>
/// Extension method to convert dynamic data to a DataTable. Useful for databinding.
/// </summary>
/// <param name="items"></param>
/// <returns>A DataTable with the copied dynamic data.</returns>
public static DataTable ToDataTable(this IEnumerable<dynamic> items) {
    var data = items.ToArray();
    if (data.Count() == 0) return null;

    var dt = new DataTable();
    foreach(var key in ((IDictionary<string, object>)data[0]).Keys) {
        dt.Columns.Add(key);
    }
    foreach (var d in data) {
        dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
    }
    return dt;
}
Benioff answered 9/6, 2011 at 20:14 Comment(1)
How could you get two way databinding thenAmoakuh
S
2

If we are talking GridView (meaning not WPF) then impromptu can proxy an expando to a poco given an interface. Say we have a list of expando's you can convert them to poco's:

IEnumerable<IMyInterface> listOfPocos
       = Impropmtu.AllActLike<IMyInterface>(listOfExpandos, typeof(INotifyPropertyChanged));
Subjoin answered 20/6, 2011 at 13:48 Comment(0)
E
2

I adapted Brian's accepted answer to be a little more concise and LINQ-y:

public static DataTable ToDataTable(this IEnumerable<dynamic> items)
{
    var list = items.Cast<IDictionary<string, object>>().ToList();
    if(!list.Any()) return null;

    var table = new DataTable();
    list.First().Keys.Each(x => table.Columns.Add(x));
    list.Each(x => x.Values.Each(y => table.Rows.Add(y)));

    return table;
}

(This assumes you've defined an IEnumerable.Each extension, which every codebase I've worked on has had).

Endogen answered 5/6, 2013 at 22:0 Comment(3)
Why use an Each Extension when "List<T>" has a ForEach method doing the same thingCowbell
Because otherwise you need to cast Keys and Values (which are IEnumerable<T>) to List<T>.Endogen
I would say just use foreach on IEnumerable<T> when you aren't returning a result.Free
B
2

I came to this thread after researching on the same topic, I found no solution but constructed my own as I desperately needed this one. So here is my solution without going POCO that really works.

// Fill "list" with your dynamic objects.

// cast a dynamic object to dictionary so we get the properties from it.
var props = list[0] as IDictionary<string, object>;

// create a datatable 
var table = new System.Data.DataTable();
    foreach (var c in props.Keys)
        table.Columns.Add(new DataColumn(c));

foreach (var o in list)
{
    var row = table.NewRow();
    var op =  o as IDictionary<string, object>;
    foreach (var p in op.Keys)
    {
        row[p] = op[p];
    }
    table.Rows.Add(row);
}

And simply bind this table to your grid!

I tested it and it worked for me.

Befog answered 21/12, 2013 at 18:42 Comment(0)
L
1

Ok, apparently as of now, you just can't bind a GridView control to an ExpandoObject instance. I had to use reflection to convert the ExpandoObject to a POCO class.

Lockup answered 11/4, 2011 at 1:39 Comment(1)
How did you achieve this ? Could you post samples ?Remount
C
0

adapting from Ben's answer

 public static DataTable ToDataTable(this IEnumerable<dynamic> items)
    {
        if (!items.Any()) return null;

        var table = new DataTable();
        bool isFirst = true;

        items.Cast<IDictionary<string, object>>().ToList().ForEach(x =>
        {
            if (isFirst) 
              {
                x.Keys.Select(y => table.Columns.Add(y)).ToList();
                isFirst = false;
              }
            table.Rows.Add(x.Values.ToArray());
        });

        return table;
    }
Cowbell answered 3/9, 2015 at 8:49 Comment(0)
V
0
/// <summary>
/// Extension method to convert dynamic data to a DataTable. Useful for databinding.
/// </summary>
/// <param name="items"></param>
/// <returns>A DataTable with the copied dynamic data.</returns>
public static DataTable ToDataTable(this IEnumerable<dynamic> items)
{
    var data = items.ToArray();
    if (data.Count() == 0) return null;

    var dt = new DataTable();
    foreach (var pair in ((IDictionary<string, object>)data[0]))
    {
        dt.Columns.Add(pair.Key, pair.Value.GetType());
    }


    foreach (var d in data)
    {
        dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
    }
    return dt;
}
Vapory answered 10/8, 2021 at 15:51 Comment(1)
Your answer has been included here, please remove this.Arun

© 2022 - 2024 — McMap. All rights reserved.