dka*_*man 31 wpf datagrid dynamic expandoobject
我试图在WPF数据网格中显示查询的结果.我绑定的ItemsSource类型是IEnumerable<dynamic>.由于返回的字段直到运行时才确定,因此在评估查询之前我不知道数据的类型.每个"行"都返回为ExpandoObject具有表示字段的动态属性.
我希望AutoGenerateColumns(如下所示)能够从ExpandoObject静态类型生成列,但它似乎不会.
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Results}"/>
Run Code Online (Sandbox Code Playgroud)
无论如何要以声明方式执行此操作,还是必须使用某些C#进行必要的操作?
编辑
好的,这会给我正确的列:
// ExpandoObject implements IDictionary<string,object>
IEnumerable<IDictionary<string, object>> rows = dataGrid1.ItemsSource.OfType<IDictionary<string, object>>();
IEnumerable<string> columns = rows.SelectMany(d => d.Keys).Distinct(StringComparer.OrdinalIgnoreCase);
foreach (string s in columns)
dataGrid1.Columns.Add(new DataGridTextColumn { Header = s });
Run Code Online (Sandbox Code Playgroud)
所以现在只需要弄清楚如何将列绑定到IDictionary值.
dka*_*man 28
最终我需要做两件事:
之后内置的数据绑定启动并运行良好,似乎没有任何问题获取属性值ExpandoObject.
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Results}" />
Run Code Online (Sandbox Code Playgroud)
和
// Since there is no guarantee that all the ExpandoObjects have the
// same set of properties, get the complete list of distinct property names
// - this represents the list of columns
var rows = dataGrid1.ItemsSource.OfType<IDictionary<string, object>>();
var columns = rows.SelectMany(d => d.Keys).Distinct(StringComparer.OrdinalIgnoreCase);
foreach (string text in columns)
{
// now set up a column and binding for each property
var column = new DataGridTextColumn
{
Header = text,
Binding = new Binding(text)
};
dataGrid1.Columns.Add(column);
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是clr将为ExpandoObject本身创建列 - 但不能保证一组ExpandoObjects在彼此之间共享相同的属性,引擎无法知道需要创建哪些列.
也许像Linq匿名类型的东西对你来说会更好.我不知道你正在使用什么类型的数据网格,但绑定对于所有这些都应该是相同的.这是telerik数据网格的一个简单示例.
链接到telerik论坛
这实际上并不是真正动态的,需要在编译时知道类型 - 但这是在运行时设置类似这样的简单方法.
如果你真的不知道你将展示什么样的领域,问题就会变得多毛了.可能的解决方案是
使用动态linq,您可以在运行时使用字符串创建匿名类型 - 您可以根据查询结果进行汇编.第二个链接的示例用法:
var orders = db.Orders.Where("OrderDate > @0", DateTime.Now.AddDays(-30)).Select("new(OrderID, OrderDate)");
Run Code Online (Sandbox Code Playgroud)
无论如何,基本思想是以某种方式将itemgrid设置为一组对象,这些对象的共享公共属性可以通过反射找到.