Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you bind Dapper query result to WPF DataGrid

Here's my code. It produces a bound grid with the correct number of rows, however the cells are empty.

XAML

<DataGrid
  Name="grid" 
  ItemsSource="{Binding}"
  AutoGenerateColumns="True" />

Code behind

grid.DataContext = cn.Query("select * from SomeTable");
like image 302
Seth Reno Avatar asked Nov 08 '12 23:11

Seth Reno


3 Answers

From the docs, your syntax there -- cn.Query("sql") -- returns a list of dynamic-typed objects (IEnumerable<dynamic>). That won't work for the DataGrid auto-columns, which looks for concrete members to generate its columns. I'd suggest creating a simple entity class for SomeTable to map the properties and then using cn.Query<SomeTableEntity>("select * from SomeTable");.

like image 177
McGarnagle Avatar answered Sep 29 '22 10:09

McGarnagle


So I guess the answer is: it's not possible. Here's a hacky workaround.

        ...
        var items = cn.Query("select * from SomeTable");
        grid.DataContext = ConvertToDataTable(items);
    }

    public DataTable ConvertToDataTable(IEnumerable<dynamic> items) {
        var t = new DataTable();
        var first = (IDictionary<string, object>)items.First();
        foreach (var k in first.Keys)
        {
            var c = t.Columns.Add(k);
            var val = first[k];
            if (val != null) c.DataType = val.GetType();
        }

        foreach (var item in items)
        {
            var r = t.NewRow();
            var i = (IDictionary<string, object>)item;
            foreach (var k in i.Keys)
            {
                var val = i[k];
                if (val == null) val = DBNull.Value;
                r[k] = val;
            }
            t.Rows.Add(r);
        }
        return t;
    }
like image 27
Seth Reno Avatar answered Sep 29 '22 12:09

Seth Reno


If you use the non-generic version of Query, it returns a dynamic representation of the data. The dynamic API is not suitable for most UI data-bindings. It would be preferable to use the generic Query<T> API to load the data into types that have defined properties.

At a complete push, it would also theoretically be possible to implement ITypedList on the data and expose the properties accordingly. But that is quite a lot of work for not so much gain.

like image 37
Marc Gravell Avatar answered Sep 29 '22 12:09

Marc Gravell