Changing the Page Size Interactively in a DataGrid Web Control - The Solution (Page 3 of 5 )
The obvious solution is to change the CurrentPageIndex together with the PageSize to bring it always inside the modified admissible range. But where should we move the old current page in the new page range?
We have a very simple, however not at all a user-friendly solution. No matter what the page size is we always have at least one page, the page with index 0. So with the new setting of the page size we can always set the CurrentPageIndex to 0 and make our application safely pageable:
Sub PageSizeChanged(sender As Object, e As EventArgs) MyDataGrid.PageSize=CType(ddlPageSize.SelectedItem.Text, Integer) MyDataGrid.CurrentPageIndex = 0 BindGrid End Sub
Certainly, this is not the solution we are looking for. So let’s investigate other possibilities to move the “old” current page.
Consider a user looking at a DataGrid page just before he or she changes the page size. The user is seeing PageSize records on the page with the CurrentPageIndex index, the “old” current page. Where should we move this “old” current page after the user changed the page size? Which new sized page should we display? A good choice is to display a “new” current page with almost the same records as on the “old” current page. Now what means “almost the same records”?
At the moment the user is looking at a page, we know the “old” CurrentPageIndex and the “old” PageSize and so it is easy to find out which records are on the page. After re-arranging the data source we could display the page containing the first record displayed on the old page. Clearly, the first record is an arbitrary choice. The second, the third, …, the last record on the old page would do the same job as well.
In all these cases the user would be no more than one page away from the last viewed records. She or he would see a page certainly containing the first (or the second, …, or the last) record of the old page, and to see all the “old” records the user would at most move to the next (or the previous) page in the new arrangement.
Let me explain how this is to achieve.
If intOldPageSize is the old page size and the current page index is CurrentPageIndex, then the first record's index on the current page will be given by
Changing the page size we know the “new” PageSize. Let’s save this value in the variable intNewPageSize. To calculate the position in the new arrangement of the record having the index intFirstRecordIndex we need to know the total page number in the new arrangement. Note that we cannot use the DataGrid control's PageSize property, because we have not yet re-bind to the data source the control with the new page size set.
So we must do the calculation ourselves every time we change the page size. For that, by every change of the page size, we need the total number of records in the data source. To access the total number of records across subsequent postbacks we will save this value in a session-level variable. Therefore, add these lines just before the last command in the CreateDataSource function:
' save the record count to a session variable for ' access across subsequential postbacks Session("recCount")=dt.Rows.Count
and suppose we assigned this value to a local variable intRecordCount. The new page count intNewPageCount is then given by
If the division of the total record number by the new page size has no remainder, then the result will be the new page number. If this division has a remainder we must increment the result with one for the "incomplete" last page. This is automatically done by the function Math.Ceiling.
Now in the new arrangement it is easy to find the page containing the record having the index intFirstRecordIndex:
Dim i as Integer For i = 1 to intNewPageCount If intFirstRecordIndex >= (i-1)*intNewPageSize +1 And _ intFirstRecordIndex <= i*intNewPageSize Then intNewCurrentPageIndex=i-1 Exit For End If Next i
We iterate through the new pages. On the i-th page the first record has the index (i-1)*intNewPageSize +1, while the last record has the index i*intNewPageSize. We catch the index intNewCurrentPageIndex of the page containing our old top record with index intFirstRecordIndex.
Now before we re-bind the DataGrid having the new page size set, we set the new current page index to intNewCurrentPageIndex and we are done.