如何在不生成列错误的情况下将对象列表传递给 gridview 数据源

How to pass a list of objects to a gridview datasource without generating a column error

我执行基本的 SQL 查询以将数据提供给 Gridview 排序事件。

public DataTable GetDataDataTableGeneric()
{
    string query = "SELECT * FROM Gamer";

    SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AzureServer"].ConnectionString);
    conn.Open();

    SqlCommand cmd = new SqlCommand(query, conn);

    DataTable dt = new DataTable();
    dt.Load(cmd.ExecuteReader());

    conn.Close();
    return dt;
}

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
    // string query= e.SortExpression + " " + GetSortDirection(e.SortExpression);
    // e.SortExpression;
    DataTable dt = GetDataDataTableGeneric();
    dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);

    List<DataRow> list = dt.AsEnumerable().ToList();

    GridView1.DataSourceID = null;

    GridView1.DataSource = list;
    GridView1.DataBind();
}

由于数据源不接受不可枚举的对象,我决定将数据表转换为列表。

但是,我得到这个错误:

'System.Data.DataRow' does not contain a property with the name 'Id'.

有没有办法生成列表并避免错误?

更新 功能:

        protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
    {

        DataTable dt = GetDataDataTableGeneric();
        dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
    //    List<Gamer> list = dt.AsEnumerable().ToList();
        List<Gamer> list = (from DataRow row in dt.Rows
         select new Gamer
         {
             //assign properties here
             Id = Convert.ToInt32(row["Id"]),
             UserID = Convert.ToInt32(row["UserID"]),
             Level = Convert.ToInt32(row["Level"]),
             Loyalty = Convert.ToInt32(row["Loyalty"]),
             Experience = Convert.ToInt32(row["Experience"]),
             OverallPoints = Convert.ToInt32(row["OverallPoints"]),
             OverallBets = Convert.ToInt32(row["OverallBets"]),
             Login = row["Login"].ToString()

         }).ToList();

        GridView1.DataSourceID = null;
        GridView1.DataSource = list;
        GridView1.DataBind();

    }

错误

The data source does not support sorting.

以下解决方案也失败了。导致同样的排序问题。

    protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
    {

       DataTable dt = GetDataDataTableGeneric();
        dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
        List<Gamer> list = (from DataRow row in dt.Rows
         select new Gamer
         {
             //assign properties here
             Id = Convert.ToInt32(row["Id"]),
             UserID = Convert.ToInt32(row["UserID"]),
             Level = Convert.ToInt32(row["Level"]),
             Loyalty = Convert.ToInt32(row["Loyalty"]),
             Experience = Convert.ToInt32(row["Experience"]),
             OverallPoints = Convert.ToInt32(row["OverallPoints"]),
             OverallBets = Convert.ToInt32(row["OverallBets"]),
             Login = row["Login"].ToString()

         }).ToList();
        DataTable dt2 = ConvertToDataTable(list);
        GridView1.DataSourceID = null;
        GridView1.DataSource = dt2;
        GridView1.DataBind();

    }


    private DataTable ConvertToDataTable<T>(IList<T> data)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
        {
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
            {
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            }
            table.Rows.Add(row);
        }
        return table;
    }

以下解决方案也未能奏效:

        string cmd = "SELECT * FROM Gamer ORDER BY "+ e.SortExpression + " " + GetSortDirection(e.SortExpression);
        DataSet ds = new DataSet();
        using (SqlConnection connection = new SqlConnection(connectionString))
        {

            SqlDataAdapter sqlAdapter = new SqlDataAdapter(cmd, connection);

            sqlAdapter.Fill(ds);
        }
        GridView1.DataSource = ds;
        GridView1.DataBind();

这没有意义,实际上通过将它转换为 List<DataRow> 而你没有将它转换为 List<Gamer>,所以这种方式是行不通的。

你可以直接绑定数据table:

GridView1.DataSource = dt;
GridView1.DataBind();

或者相反的方法是创建一个 class 这将是一个 DTO 反对你的 table :

public class Gamer
{
   public int Id {get;set;}
}

然后是您的代码,您可以从 DataTable 或数据访问中创建一个 List<Gamer>,您可以直接 return List<Gamer>.

如果您采用第一种方法,您的方法代码将如下所示:

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{

    DataTable dt = GetDataDataTableGeneric();
    dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);

    GridView1.DataSource = dt;
    GridView1.DataBind();
}

希望对您有所帮助。

您可以使用多个选项,但最简单的一个

    DataTable dt = GetDataDataTableGeneric();
    dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
GridView1.DataSource = dt.DefaultView.ToTable();
    GridView1.DataBind();

或者您可以使用以下函数从 Query 动态创建 table,然后将其分配给 GridView

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        NorthwindEntities entity = new NorthwindEntities();
        var db1 = (from ordermst in entity.Orders
                    where ordermst.ShipCountry.Equals("Finland")
                    select new
                    {
                        CustomerID = ordermst.CustomerID,
                        OrderID = ordermst.OrderID
                    }).Take(10).ToList();
        DataTable dt = ConvertToDataTable(db1);
        GvOrder.DataSource = dt;
        GvOrder.DataBind();
 
        DataTable dt1 = new DataTable();
        dt1 = GvOrder.DataSource as DataTable;
        GvOrder1.DataSource = dt1;
        GvOrder1.DataBind();
 
    }
}
 
private DataTable ConvertToDataTable<T>(IList<T> data)
{
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    foreach (PropertyDescriptor prop in properties)
    {
        table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
    }
    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
        {
            row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        }
        table.Rows.Add(row);
    }
    return table;
}

奇怪的是,要使它正常工作,您只需要放置一个空的事件处理程序即可。

 protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
        {}