这是我的代码。它生成一个具有正确行数的绑定网格,但单元格为空。
XAML
<DataGrid
Name="grid"
ItemsSource="{Binding}"
AutoGenerateColumns="True" />
背后的代码
grid.DataContext = cn.Query("select * from SomeTable");
答案 0 :(得分:5)
从docs,您的语法 - cn.Query("sql")
- 返回动态类型对象列表(IEnumerable<dynamic>
)。这对于DataGrid自动列不起作用,后者查找具体成员生成其列。我建议为 SomeTable 创建一个简单的实体类来映射属性,然后使用cn.Query<SomeTableEntity>("select * from SomeTable");
。
答案 1 :(得分:5)
所以我猜答案是:这是不可能的。这是一个hacky解决方法。
...
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;
}
答案 2 :(得分:3)
如果使用非泛型版本的Query,它将返回数据的动态表示。动态API不适合大多数UI数据绑定。最好使用通用Query<T>
API将数据加载到已定义属性的类型中。
在完全推送中,理论上也可以在数据上实现ITypedList并相应地公开属性。但这并不是很多工作,而是没有那么多的收获。
答案 3 :(得分:0)
使用纯 Linq 是不可能的!可以重用OLD数据集并使用System.Data.DataSetExtensions转换回linq。 (不优雅,但有效)
// Steal concrete connection from Linq
ModelDEmoWPFContainer l_ctx = new ModelDEmoWPFContainer();
var l_connection = (System.Data.EntityClient.EntityConnection)l_ctx.Connection)
.StoreConnection;
System.Data.SqlClient.SqlCommand l_cmd =
new System.Data.SqlClient.SqlCommand(query_arg);
l_cmd.Connection = (System.Data.SqlClient.SqlConnection) l_connection;
System.Data.SqlClient.SqlDataAdapter l_da =
new System.Data.SqlClient.SqlDataAdapter(l_cmd);
System.Data.DataSet l_ds = new System.Data.DataSet();
l_da.Fill(l_ds);
CLONE元数据
System.Data.DataTable l_dt = l_ds.Tables[0].Clone();
通过System.Data.DataSetExtensions
返回linqvar dt = (from data in l_ds.Tables[0].AsEnumerable()
select data).ToList();
foreach (DataColumn column in l_dt.Columns)
{
var binding = new Binding(string.Format("[{0}]", column.Ordinal));
datagrid.Columns.Add(new DataGridTextColumn()
{ Header = column.ColumnName, Binding = binding });
}
datagrid.ItemsSource = dt;
答案 4 :(得分:0)
如果您使用的是MVVM模式,我认为这是更好的解决方案:
在ViewModel中创建ObservableCollecion,它将绑定到ItemSource
中的DataGrid
:
public ObservableCollection<T> bindableCollection;
然后,从数据库中获取数据,例如:
public void RefreshDataGrid(){
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings[
"RecipeManager.Properties.Settings.RecipeManagerConnectionString"].ConnectionString)){
var fetchedData = conn.Query<Flavour>("select * from [Flavour]");
ConvertToDataTable(fetchedData);
}
}
最后一步,也是最重要的创建函数,它将IEnumerable添加到你的ObservableCollection:
private void ConvertToObservableCollection(IEnumerable<Flavour> items){
ObservableCollection<Flavour> flavours = new ObservableCollection<Flavour>();
foreach (var item in items){
Flavour flavour = item as Flavour;
flavours.Add(new Flavour(flavour.Name,flavour.Company,flavour.Shop,flavour.Amount));
}
Flavours = flavours;
}
我认为,这是mvvm的好方法。