How to format your GridView autogenerated columns

The first step is getting hold of the autogenerated column. Luckily the GridView control has a virtual method called CreateAutoGeneratedColumn which returns a AutoGeneratedField. So create a control that inherits GridView, override this method, take the generated field in the base method, change DataFormatString. I couldn't find any way to do that except with reflection. I noticed that the value of the DataFormatString property was stored in the ViewState of the AutoGeneratedField, so I used reflection to get to it, then I changed the value.
This is the code:
protected override AutoGeneratedField CreateAutoGeneratedColumn(
AutoGeneratedFieldProperties fieldProperties)
{
AutoGeneratedField field =
base.CreateAutoGeneratedColumn(fieldProperties);
StateBag sb = (StateBag)field.GetType()
.InvokeMember("ViewState",
BindingFlags.GetProperty |
BindingFlags.NonPublic |
BindingFlags.Instance,
null, field, new object[] {});
sb["DataFormatString"] = "{0:N}"; //or the format string you prefer
field.HtmlEncode=false; //see update
return field;
}
Update:
The BoundField object formats values differently depending on html encoding. If the html encoding is enabled, then the value is transformed into a string, then the formatting is applied. That means that number formatting will NOT work when html encoding is true.
That is why I've added the field.HtmlEncode=false; line above. A more secure option would be to make the HtmlEncode property depend on the field.DataType.
Update2:
While this works, I don't recommend doing it like that. I am using it because I have custom user controls that inherit from the GridView and I need to cover the AutoGeneratedColumns=true case. It is much easier to generate your columns yourself from the DataSource using BoundField objects (Or any other DataControlField objects) that you add to the GridView.Columns collection.