2012-11-08 71 views
7

這是我的代碼。它會生成具有正確行數的綁定網格,但單元格爲空如何將Dapper查詢結果綁定到WPF DataGrid

XAML

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

代碼背後

grid.DataContext = cn.Query("select * from SomeTable"); 
+1

你有沒有試過給它一個類型? 'cn.Query (...);' – mxmissile

+0

我需要保持它的通用性,因爲網格根據用戶輸入綁定到不同的類型。 –

回答

5

docs,你的語法有 - cn.Query("sql") - 返回動態類型對象(IEnumerable<dynamic>)的列表。這對於DataGrid自動列不起作用,它會查找具體成員以生成其列。我建議創建一個簡單的實體類SomeTable來映射屬性,然後使用cn.Query<SomeTableEntity>("select * from SomeTable");

3

如果您使用非通用版本的查詢,它將返回數據的動態表示形式。動態API不適用於大多數UI數據綁定。最好使用通用Query<T> API將數據加載到具有已定義屬性的類型中。

完成推送,理論上也可以在數據上實現ITypedList並相應地顯示屬性。但是,這不是太好的收穫,這是相當多的工作。

5

所以我想答案是:這是不可能的。這是一個怪異的解決方法。

 ... 
     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; 
    } 
+0

我會說這不是很冒險,而且是一個很好的解決方案。 –

+0

謝謝,我有這個相同的問題,這沒有把戲。 – Tofystedeth

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();  

回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; 
0

如果使用MVVM模式,我認爲這是更好的解決方案:

在您的ViewModel中創建ObservableCollecion,它將綁定到ItemSourceDataGrid

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的好方法。