【问题标题】:Databind Dynamic Control Type And Name数据绑定动态控件类型和名称
【发布时间】:2012-09-24 08:16:26
【问题描述】:

我正在研究一种方法来制作我的所有 SQL 查询,然后将它们数据绑定到中继器、数据列表等......

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 时它不知道控件类型..

那我该怎么做呢?

【问题讨论】:

    标签: c# asp.net .net controls


    【解决方案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);
    
            }
        }
    

    }

    【讨论】:

    • dataSourceProp.SetValue(control, dt): 方法 'SetValue' 没有重载需要 2 个参数
    • 工作就像一个魅力,如果你能解释你在做什么,那就太好了:)因为它有效,但我不明白为什么:)
    • 这是次优解决方案,因为不需要反射 - 可以使用强制转换为 BaseDataBoundControl(请参阅我的答案)
    【解决方案2】:

    接受的答案错误地假设.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)
    

    【讨论】:

      猜你喜欢
      • 2010-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-01
      • 1970-01-01
      • 2011-06-02
      • 2011-01-04
      • 2012-01-29
      相关资源
      最近更新 更多