這是我的代碼。它會生成具有正確行數的綁定網格,但單元格爲空。如何將Dapper查詢結果綁定到WPF DataGrid
XAML
<DataGrid
Name="grid"
ItemsSource="{Binding}"
AutoGenerateColumns="True" />
代碼背後
grid.DataContext = cn.Query("select * from SomeTable");
這是我的代碼。它會生成具有正確行數的綁定網格,但單元格爲空。如何將Dapper查詢結果綁定到WPF DataGrid
XAML
<DataGrid
Name="grid"
ItemsSource="{Binding}"
AutoGenerateColumns="True" />
代碼背後
grid.DataContext = cn.Query("select * from SomeTable");
從docs,你的語法有 - cn.Query("sql")
- 返回動態類型對象(IEnumerable<dynamic>
)的列表。這對於DataGrid自動列不起作用,它會查找具體成員以生成其列。我建議創建一個簡單的實體類SomeTable來映射屬性,然後使用cn.Query<SomeTableEntity>("select * from SomeTable");
。
如果您使用非通用版本的查詢,它將返回數據的動態表示形式。動態API不適用於大多數UI數據綁定。最好使用通用Query<T>
API將數據加載到具有已定義屬性的類型中。
在完成推送,理論上也可以在數據上實現ITypedList並相應地顯示屬性。但是,這不是太好的收穫,這是相當多的工作。
所以我想答案是:這是不可能的。這是一個怪異的解決方法。
...
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;
}
我會說這不是很冒險,而且是一個很好的解決方案。 –
謝謝,我有這個相同的問題,這沒有把戲。 – Tofystedeth
這是不可能用純的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();
回LINQ通過System.Data.DataSetExtensions
var 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;
如果使用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的好方法。
你有沒有試過給它一個類型? 'cn.Query(...);' –
mxmissile
我需要保持它的通用性,因爲網格根據用戶輸入綁定到不同的類型。 –