数据绑定动态控制类型和名称

时间:2012-10-03 11:49:56

标签: c# asp.net .net controls

我正在研究一种方法来制作我的所有SQL查询,然后将它们数据绑定到Repeater,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");

但是,当我只使用Control时,它现在不起作用,因为它不知道控制类型。

那我该怎么做?

2 个答案:

答案 0 :(得分: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);

        }
    }

}

答案 1 :(得分:0)

接受的答案错误地假设.DataSource属性只能通过Reflection获得。

具有此属性的所有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)