In my .aspx page, I have an <asp:GridView runat="server" ID="CustomerGridView"> control which I bind like this:
public partial class InsertCustomer : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewCustomer();
}
}
private void ViewCustomer()
{
var manager = new DomainManager();
var result = manager.FindAll(new Customer());
this.CustomerGridView.DataSource = result;
this.CustomerGridView.DataBind();
}
}
Here is the DomainManager class:
public class DomainManager
{
readonly StringBuilder _queryBuilder = new StringBuilder();
private Type _entityType;
readonly SQLHelper _sqlHelper = new SQLHelper();
public IEnumerable FindAll<T>(T entity)
{
_entityType = entity.GetType();
var query = string.Format("select * from {0}", _entityType.Name);
var dt = _sqlHelper.FillDataTable(query);
return dt.AsEnumerable();
}
}
The problem is that my grid is not being bound correctly. Why not?
Try changing
to
Explanation: By default, a
GridViewbinds to actual properties of an object. For example, if the data source is aList<Customer>, then you can bind to theNameproperty of eachCustomer. But when the data source is aDataTableof customers, then each customer is represented by aDataRow, and aDataRowdoes not have aNameproperty that theGridViewcan bind to.To support dynamic properties, an object must implement the
ICustomTypeDescriptorinterface. This interface is implemented byDataRowViewbut notDataRow. By changing the code to returndt.DefaultView(which is aDataView), you provide theGridViewwith a collection ofDataRowViewobjects that it can bind to.Now you might be wondering why
works, but
doesn’t.
The reason is that
DataTableimplements theIListSourceinterface, which tells theGridView“don’t use me as the data source, use myDefaultViewinstead.” ButAsEnumerable()returns a wrapper object that doesn’t implementIListSource, so theGridViewdoesn’t know how to get to theDefaultView.