2012-10-03 62 views
0

林上的方法努力使我所有的SQL Querys,然後數據綁定他們中繼器,DataLists等等......數據綁定動態控制的類型和名稱

protected void sqlQuery(Control controlName, String query) { 
    SqlConnection conn = new SqlConnection(); 
    SqlCommand cmd = new SqlCommand(); 

    conn.ConnectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString(); 
    cmd.Connection = conn; 

    try { 
     cmd.CommandText = query; 

     DataTable dt = new DataTable(); 
     SqlDataAdapter adapter = new SqlDataAdapter(cmd); 

     adapter.Fill(dt); 
     controlName.DataSource = dt; 
     controlName.DataBind(); 

    } catch (Exception error) { 
     Label1.Text = "Error!<br/>" + error; 
    } 
} 

,那麼我會調用該方法與我的控制姓名,我想要數據綁定。 像:

sqlQuery(Repeater1, "SELECT * FROM someTable"); 
sqlQuery(DataList1, "SELECT * FROM someTable"); 

但現在dosent工作,因爲它不知道的控制類型時,我只是用控制..

因此,如何將我做到這一點?發生

回答

1

該問題是因爲Control不具有屬性/您所需要的方法,並且這些屬性不會上的接口或基地控制類型來定義。

因此,你必須使用一種叫做reflection的東西,它允許你調用你需要的屬性和方法(以及許多其他的東西),而不需要編譯時知道這些,當然如果你傳入如果沒有這些控制,你會得到一個令人討厭的異常,並且在使用反射時性能會受到影響 - 但在你的情況下,這將是微不足道的。

我沒有沿着這些線路的IDE方便,但事情應該這樣做。

public static void DatabindControlFromSqlQuery(Control control,string query) 
{ 
    var connectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString(); 
    using (var connection = new SqlConnection(connectionString)) 
    { 
     using (var cmd = new SqlCommand(connection)) 
     { 
      cmd.CommandText = query; 
      var dt = new DataTable(); 
      var adapter = new SqlDataAdapter(cmd); 
      adapter.Fill(dt); 

      var type = control.GetType(); 
      var dataSourceProp = type.GetProperty("DataSource"); 

      dataSourceProp.SetValue(control,dt); 

      var dataBindMethod = type.GetMethod("DataBind"); 
      dataBindMethod.Invoke(control,null); 

     } 
    } 

}

+0

dataSourceProp.SetValue(控制,DT):無重載方法「的SetValue」需要兩個參數 –

+0

NULL傳遞給第三個參數 –

+0

Wor ks就像一個魅力,如果你能解釋你在做什麼,那會很棒:)它可以工作,但我不明白爲什麼:) –

0

接受的答案錯誤地假定.DataSource屬性只能通過反射來得到。

有這個酒店的所有ASP.NET控件從System.Web.UI.WebControls.BaseDataBoundControl衍生所以你可以寫這樣的代碼(無反射,所以會快很多):

protected void sqlQuery(Control controlName, String query) { 
    // cast the control to the base class 
    var controlWithDataSource = controlName as BaseDataBoundControl; 
    if (controlWithDataSource == null) 
     throw new ArgumentException("Control does not inherit BaseDataBoundControl."); 

    SqlConnection conn = new SqlConnection(); 
    SqlCommand cmd = new SqlCommand(); 

    conn.ConnectionString = ConfigurationManager.ConnectionStrings["SqlConn"].ToString(); 
    cmd.Connection = conn; 

    try { 
     cmd.CommandText = query; 

     DataTable dt = new DataTable(); 
     SqlDataAdapter adapter = new SqlDataAdapter(cmd); 

     adapter.Fill(dt); 

     // here reference the new control 
     controlName.DataSource = dt; 
     controlName.DataBind(); 

    } catch (Exception error) { 
     Label1.Text = "Error!<br/>" + error; 
    } 
} 

這或許對你來說可能你的方法的簽名更改這個類,所以你不需要鑄造在所有

protected void sqlQuery(BaseDataBoundControl controlName, String query)