Today I faced an interesting problem regarding
GridView. We are using a enhanced
GridView control as a reusable component in different applications.
In one of the application, we got an issue :
when all the rows in the Gridview get deleted - we still need to show the Header portion of the Gridview with the "No rows" information displayed on the first row.
Its very simple to do, just
bind the
GridView to its
datasource with 1 empty row and then while rendering, remove all controls from the 1st row and render only the label. The problem we faced was we did not know the
Type of
GridView's datasource. We can not
hardcode as its a bad practice and also we did not know which types are being
binded to the
Gridview by the Page developers of the application.
So we have to find out the type of the
datasource then create an instance of it and then add a new object of that type in to the
datasource so the
gridview gets rendered. I tried something like :
Type T = GridView1.DataSource.GetType();
T newRow = (T)Activator.CreateInstance(T);This is something I wanted but the problem is that Activator.
CreateInstance() returns an object of Type Object and the generic T can not be used to cast it. This gives a compilation error. Without the cast, I cannot do something like :
GridView1.DataSource.Add(newRow);which is what I want. To overcome it I had to somehow force .NET to recognize the Object as of Type T and allow me to add it to the
GridView1.
DataSource.
To achieve it, I tried a hack which worked. Its a mix of reflection and generics and looks like:
Type T = GridView1.DataSource.GetType();
Type V = T.GetGenericArguments()[0];
Object o = Activator.CreateInstance(V);
Object[] ObjectArray = new Object[]{o };
T.GetMethod("Add").Invoke(GridView1.DataSource, ObjectArray);
GridView1.DataBind();As the
datasource for the
GridView always implements
IEnumerable interface we did the following steps:
- First get the Type of the Datasource which was like List
- Used "GetGenericArguments" to get the Type of the Object of the GenericType object.
- Created an instance of that GenericType
- We need an Array of object to call the reflection method.
- Use Reflection to add the Add method and pass the Object Array hosting the GenericType object.
- Bind the Grid
Now although .NET did not allow us the explicitly cast the GenericObject to its Type, it allowed us to do it in runtime.
I think, .NET should allow us to do in explicitly as thats more intuitive than this cumbersome way. Anyone having a better approach to this problem , please comment below.