Reordering columns without binding data
In my last post, I say if you want reorder DataGrid columns on the client (e.g., using drag-and-drop) then you must rebind the data source on the server to have the changes persisted at least across the session. The persistence wouldn't work across application/session restarts because no disk persistence is implemented.
However, the following comment made me thinking a little more about the whole subject. (Basically, I spent 90% of my yesterday workday solving this issue.)
I still think that the concept of rebinding in order to persist column position is wrong. The column position is only a form of a presentation. It should not be related in any way, to my opinion, to its underlying data (unlike sorting, which, as you mentioned in your (great) blog, is better done on the server).
I don't think we would ever come to an agreed point if we start a thread about the interpretation of column reordering. As a matter of fact, ASP.NET suggests to use the IPostBackDataHandler interface whenever client-side changes affect the state (including presentation) of a server control. This is definitely the case, I believe, with grid columns. In light of this, I firmly believe that implementing that interface is the correct way to go and is respectful of the currently set programming rules.
If we proceed this way, rebinding is necessary to have the grid taking into account the new column order. By firing a server-side event, we reduce this to the very minimum. However, a challenging question is still lying in the above comment. Can we do better and eliminate the necessity to rebind?
I haven't tried it yet but I think that another way might exist--storing the
ColumnOrder value (the comma-separated string with the new order of columns) out of the viewstate in a separate hidden field. If you look at my
source code, you probably recognize out of commented lines that I originally wrote it using a separate hidden field. When the
DataGrid is initialized, the sequence of events is:
- OnInit
- CreateColumnSet called to create the grid without binding (i.e., from columns viewstate)
- LoadViewState (ColumnOrder is empty and gets updated only at THIS time)
- Page_Load
With ColumnOrder stored in the viewstate and automatically restored using the recommended IPostBackDataHandler interface, the earlier you get involved is after LoadViewState. ColumnOrder gets its updated value too late to affect the column order in the grid. If you rebind, you fix it.
However, since CreateColumnSet is still called before LoadViewState is invoked, if you figure out a way to have ColumnOrder set with the client value in OnInit that might work. ASP.NET doesn't allow you to modify the viewstate, but if you store ColumnOrder in a separate hidden field, you can read it at any time using the plain old Page.Request method. If you come up with the following sequence of events, it should work without rebinding.
- OnInit
- ColumnOrder = Page.Request["YourHiddenField"]
- CreateColumnSet called to create the grid without binding (i.e., from columns viewstate)
- LoadViewState
- Page_Load
Of course, for this to happen you need to modify the HTC accordingly.