0

私は、すべての SQL クエリを作成し、それらをリピーター、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");

しかし、コントロールを使用するだけではコントロールの種類がわからないため、現在は機能していません。

では、どうすればこれを行うことができますか?

4

2 に答える 2

1

この問題はControl、必要なプロパティ/メソッドがなく、これらのプロパティがインターフェイスまたはベース コントロール タイプで定義されていないために発生します。

したがって 、リフレクションと呼ばれるものを使用する必要があります。これにより、コンパイル時の知識がなくても、必要なプロパティとメソッド (および他の多くのもの) を呼び出すことができます。もちろん、これらなしでコントロールを渡す場合は、厄介な例外が発生し、リフレクションを使用するとパフォーマンスが低下しますが、あなたの場合は簡単です。

私は便利な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);

        }
    }

}

于 2012-10-03T12:02:59.437 に答える
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)
于 2012-11-13T15:11:07.113 に答える