Reputation: 122202
I haven't worked with GridView too much and after poking around with it, find it to be more complex than I need but missing some very basic abilities that I would expect it to have. No doubt its implementation makes sense given its 90% of the time purpose of being bound to a dataset especially when doing this declaratively, but I intend to bind it to an IEnumerable<T>
in code.
What I need is the ability to do the following easily
IEnumerable<T>
where the columns can be limited to only certain properties of type T
basically something implementing the following interface would be nice
public interface IEasyGridBinder {
void Bind<T>(IEnumerable<T> bindableObjects, params string[] propertiesToBind);
IList<IDictionary<string, string>> Values {get;}
}
So to get this, should I write my own custom EasyGridBinder that inherits from GridView and implements this interface or is there a really simple way to do these things that I am just unfamiliar with?
P.S. Bonus points if I can write something like
myGrid.Bind(myEntities, e=>{e.Id; e.Name; e.Customer.Name;});
But I suppose I can figure that out myself after reading up on expressions
Follow-up question: Is there no way to get the original data that was input into the gridview and has not been converted to html? If a field received as input an empty string the cell seems to contain " " so is there no way to distinguish between an input of an empty string and a space? If this is indeed the case then I probably WILL end up re-implementing most of GridView's functionality.
Upvotes: 3
Views: 445
Reputation: 26514
If you set the GridViews AutoGenerateColumns property to false it will only generated the columns you specify. You do that by creating BoundFields and adding them to the Gridview Columns collection.
GridView gv = new GridView();
gv.AutoGenerateColumns = false;
BoundField bf = new BoundField();
bf.DataField = "Id";
bf.HeaderText = "ID";
gv.Columns.Add(bf);
BoundField bf = new BoundField();
bf.DataField = "Name";
bf.HeaderText = "Name";
gv.Columns.Add(bf);
BoundField bf = new BoundField();
bf.DataField = "Customer.Name";
bf.HeaderText = "Customer Name";
gv.Columns.Add(bf);
gv.DataSource = IEnumerable<T>;
gv.DataBind();
I had written this explanation up in the comments but figured I'd move it out to where it was more visible and add a code example:
To make the above dynamic create a GridViewDisplayAttribute class which inherits from Attribute. Give GridViewDisplayAttribute a HeaderText property. Decorate the properties of of T specifying HeaderText. By iterating the properties of T creating BoundFields for each decorated property utilizing HeaderText.
Quick untested code example:
using System;
public class GridViewDisplayAttribute : Attribute
{
public GridViewDisplayAttribute(string headerText)
{
HeaderText = headerText;
}
public readonly bool HeaderText;
}
GridView gv = new GridView();
gv.AutoGenerateColumns = false;
Type t = <T>.GetType();
PropertyInfo[] pis = t.GetProperties();
foreach (PropertyInfo pi in pis)
{
GridViewDisplayAttribute[] gvdaArray = pi.GetCustomAttributes(
typeof(GridViewDisplayAttribute), true);
foreach (GridViewDisplayAttribute gvda in gvdaArray)
{
BoundField bf = new BoundField();
bf.DataField = pi.Name;
bf.HeaderText = gvda.HeaderText;
}
gv.Columns.Add(bf);
}
gv.DataSource = IEnumerable<T>;
gv.DataBind();
Upvotes: 1
Reputation: 10071
LinqDataSource allows you to specify your object as the backing store for the data source. You'd then bind the GridView to that datasource. It's a bit more declaration in the .aspx, but it's less code to maintain later as feature bloat brings you closer and closer to reimplementing GridView.
Upvotes: 2
Reputation: 34573
I would recommend using extension methods to add the required behavior. The only downside to that is that you can't add "Values" as a property.
Upvotes: 0