In order to use the DataGrid's built-in paging, the DataSource must implement ICollection (so that the DataGrid can determine the total count of records in the DataSource and hence the number of pages that will be needed. An IDataReader implements the IEnumerable rather than ICollection interfaces as one cannot determine the total number of records without enumerating through the data.
As has been mentioned, there is no simple type conversion from IDataReader to a DataSet. The process would involve enumerating though the records and adding them one by one to the rows of a DataTable.
Rather than using SqlHelper.ExecuteReader in your SqlDataProvider code to return an IDataReader, I would suggest that you look into using the Public Shared Sub SqlHelper.FillDataSet which populates one or more DataTables of a supplied DataSet.
Another soultion would be to use the SqlHelper.ExecuteReader in your SqlDataProvider code to return an IDataReader, but then in your module's controller code use the CBO.FillCollection method to return either an ArrayList or better yet in ASP.NET 2.0 a generic list of strongly typed objects. For example from a module I'm now working on:
Public
Function GetEPrayers(ByVal ModuleId As Integer) As List(Of EPrayerInfo)
Return CBO.FillCollection(Of EPrayerInfo)(DataProvider.Instance().GetEPrayers(ModuleId))
End Function
Either the ArrayList or the GenericList can then be passed into the DataGrid's DataSource without complaint.
Finally, if you must pass an IDataReader into the DataGrid you could enable custom paging (AllowCustomPaging=True), obtain the count of records by some other means, and pass it to the DataGrid's VirtualItemCount property. You'll also have to provide your own paging of the data.