diff --git a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataExternalSourcePage.razor b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataExternalSourcePage.razor index 54b3298967..49a00e8357 100644 --- a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataExternalSourcePage.razor +++ b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataExternalSourcePage.razor @@ -101,7 +101,7 @@ if ( !e.CancellationToken.IsCancellationRequested ) { - IEnumerable response = ( await GetDataFromExternalSource( e.Page, e.PageSize ) ); + IEnumerable response = ( await GetDataFromExternalSource( (int)e.Page, e.PageSize ) ); if ( !e.CancellationToken.IsCancellationRequested ) { diff --git a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridLargePage.razor b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridLargePage.razor new file mode 100644 index 0000000000..b4778823cf --- /dev/null +++ b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridLargePage.razor @@ -0,0 +1,62 @@ +@page "/tests/datagridlarge" + +

DataGrid on datasets larger than int.MaxValue

+ + + + + + + + +@code { + class LargeModelItem + { + public long Id { get; set; } + public string Name { get; set; } = ""; + } + + + long totalCount = 10_000_000_000_000;// + + IEnumerable items = Enumerable.Empty(); + + private void OnDataRead(DataGridReadDataEventArgs e) + { + + // if (e.ReadDataMode == DataGridReadDataMode.Virtualize) + // { + // + // items = Enumerable.Range(e.VirtualizeOffset, e.VirtualizeCount).Select(i => new LargeModelItem + // { + // Id = i, + // Name = $"Item id { i} " + // }); + // } + + if (e.ReadDataMode == DataGridReadDataMode.Paging) + { + items = LongRange((e.Page - 1) * e.PageSize, e.PageSize) + .Select(i => new LargeModelItem + { + Id = i, + Name = $"Item id {i}" + }); + } + + } + + + public static IEnumerable LongRange(long start, long count) + { + for (long i = 0; i < count; i++) + { + yield return start + i; + } + } +} \ No newline at end of file diff --git a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridPage.razor.cs b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridPage.razor.cs index 4415ad3946..b18db25669 100644 --- a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridPage.razor.cs +++ b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/DataGridPage.razor.cs @@ -27,7 +27,7 @@ public partial class DataGridPage private TableResponsiveMode responsiveMode = TableResponsiveMode.Default; private DataGrid dataGrid; - public int currentPage { get; set; } = 1; + public long currentPage { get; set; } = 1; public int currentPageSize { get; set; } = 5; private bool editable = true; diff --git a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/PagerPage.razor b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/PagerPage.razor index 2cab8418a8..925abdf1b6 100644 --- a/Demos/Blazorise.Demo/Pages/Tests/DataGrid/PagerPage.razor +++ b/Demos/Blazorise.Demo/Pages/Tests/DataGrid/PagerPage.razor @@ -51,7 +51,7 @@ - @for ( int i = context.FirstVisiblePage; i <= context.LastVisiblePage; ++i ) + @for ( long i = context.FirstVisiblePage; i <= context.LastVisiblePage; ++i ) { var pageNumber = i; @pageNumber diff --git a/Documentation/Blazorise.Docs/Pages/News/2025-05-01-release-notes-200.razor b/Documentation/Blazorise.Docs/Pages/News/2025-05-01-release-notes-200.razor index 2ba486e987..3cc66fe89c 100644 --- a/Documentation/Blazorise.Docs/Pages/News/2025-05-01-release-notes-200.razor +++ b/Documentation/Blazorise.Docs/Pages/News/2025-05-01-release-notes-200.razor @@ -26,6 +26,12 @@ DataGridSelectColumn: Multiple support + + + + DataGrid: Support for datasets larger than int.MaxValue items + + @@ -107,6 +113,33 @@ + + + + DataGrid TotalItems is now long instead of int. Here is the list of all properties that have been changed to long + + + + DataGrid: TotalItems, CurrentPage (renamed to Page in 2.0), SelectedRowIndex + + + + PaginationContext: CurrentPage, LastPage, FirstVisiblePage, LastVisiblePage, TotalItems + + + + PageButtonContext: PageNumber + + + + DataGridFilteredDataEventArgs: TotalItems + + + + DataGridReadDataEventArguments: Page + + + diff --git a/Source/Extensions/Blazorise.DataGrid/Contexts/PageButtonContext.cs b/Source/Extensions/Blazorise.DataGrid/Contexts/PageButtonContext.cs index 6a440088a7..1d3b55cb2d 100644 --- a/Source/Extensions/Blazorise.DataGrid/Contexts/PageButtonContext.cs +++ b/Source/Extensions/Blazorise.DataGrid/Contexts/PageButtonContext.cs @@ -14,7 +14,7 @@ public class PageButtonContext /// /// Button page number . /// Indicates if page is active. - public PageButtonContext( int pageNumber, bool active ) + public PageButtonContext( long pageNumber, bool active ) { PageNumber = pageNumber; Active = active; @@ -23,13 +23,13 @@ public PageButtonContext( int pageNumber, bool active ) /// /// Gets the page number. /// - public int PageNumber { get; private set; } + public long PageNumber { get; private set; } /// /// Gets the page number. /// [Obsolete( "PageNumer is deprecated and will be removed in future versions, please use PageNumber instead.", true )] - public int PageNumer { get { return PageNumber; } set { PageNumber = value; } } + public long PageNumer { get { return PageNumber; } set { PageNumber = value; } } /// /// Get the flag that indicates if the page is active. diff --git a/Source/Extensions/Blazorise.DataGrid/Contexts/PaginationContext.cs b/Source/Extensions/Blazorise.DataGrid/Contexts/PaginationContext.cs index f768d63226..6b5aa22a2b 100644 --- a/Source/Extensions/Blazorise.DataGrid/Contexts/PaginationContext.cs +++ b/Source/Extensions/Blazorise.DataGrid/Contexts/PaginationContext.cs @@ -13,7 +13,7 @@ public class PaginationContext private event PageChangedEventHandler PageChanged; - public delegate void PageChangedEventHandler( int value ); + public delegate void PageChangedEventHandler( long value ); private event PageSizeChangedEventHandler PageSizeChanged; @@ -21,17 +21,17 @@ public class PaginationContext private event TotalItemsChangedEventHandler TotalItemsChanged; - public delegate void TotalItemsChangedEventHandler( int value ); + public delegate void TotalItemsChangedEventHandler( long value ); - private int firstVisiblePage; + private long firstVisiblePage; - private int lastVisiblePage; + private long lastVisiblePage; - private int page = 1; + private long page = 1; private int pageSize = 10; - private int? totalItems; + private long? totalItems; private DataGrid parentDataGrid; @@ -58,7 +58,7 @@ public void UnsubscribeOnPageChanged( PageChangedEventHandler listener ) PageChanged -= listener; } - public void TriggerPageChange( int value ) + public void TriggerPageChange( long value ) { PageChanged?.Invoke( value ); } @@ -88,7 +88,7 @@ public void UnsubscribeOnTotalItemsChanged( TotalItemsChangedEventHandler listen TotalItemsChanged -= listener; } - public void TriggerTotalItemsChange( int value ) + public void TriggerTotalItemsChange( long value ) { TotalItemsChanged?.Invoke( value ); } @@ -132,7 +132,7 @@ private void CalculateFirstAndLastVisiblePage() /// /// Gets or sets the current page /// - public int Page + public long Page { get => page; set @@ -148,11 +148,11 @@ public int Page /// /// Gets the last page number. /// - public int LastPage + public long LastPage { get { - var lastPage = Math.Max( (int)Math.Ceiling( ( TotalItems ?? 0 ) / (double)pageSize ), 1 ); + long lastPage = Math.Max( (long)Math.Ceiling( ( TotalItems ?? 0 ) / (double)pageSize ), 1 ); if ( Page > lastPage ) Page = lastPage; @@ -164,7 +164,7 @@ public int LastPage /// /// Gets the number of the first page that can be clicked in a large dataset. /// - public int FirstVisiblePage + public long FirstVisiblePage { get { @@ -177,7 +177,7 @@ public int FirstVisiblePage /// /// Gets the number of the last page that can be clicked in a large dataset. /// - public int LastVisiblePage + public long LastVisiblePage { get { @@ -215,7 +215,7 @@ public int PageSize /// /// This field must be set only when is used to load the data. /// - public int? TotalItems + public long? TotalItems { // If we're using ReadData than TotalItems must be set so we can know how many items are available get => ( ( parentDataGrid.ManualReadMode || parentDataGrid.VirtualizeManualReadMode ) ? totalItems : parentDataGrid.FilteredData?.Count() ) ?? 0; diff --git a/Source/Extensions/Blazorise.DataGrid/DataGrid.razor.cs b/Source/Extensions/Blazorise.DataGrid/DataGrid.razor.cs index 58e48521df..6f994d9609 100644 --- a/Source/Extensions/Blazorise.DataGrid/DataGrid.razor.cs +++ b/Source/Extensions/Blazorise.DataGrid/DataGrid.razor.cs @@ -1026,7 +1026,7 @@ private async void OnPageSizeChanged( int pageSize ) await ReloadInternal( paginationContext.CancellationTokenSource.Token ); } - private async void OnPageChanged( int currentPage ) + private async void OnPageChanged( long currentPage ) { paginationContext.CancellationTokenSource?.Cancel(); paginationContext.CancellationTokenSource = new(); @@ -2172,14 +2172,22 @@ protected async ValueTask> VirtualizeItemsProviderHan ? Math.Min( request.Count, TotalItems.Value - request.StartIndex ) : request.Count; - await HandleVirtualizeReadData( request.StartIndex, requestCount, request.CancellationToken ); + await HandleVirtualizeReadData( request.StartIndex, (int)requestCount, request.CancellationToken ); await Task.Yield(); // This line makes sure SetParametersAsync catches up, since we depend upon Data Parameter. if ( request.CancellationToken.IsCancellationRequested ) return default; else - return new( Data.ToList(), TotalItems.Value ); + return new( Data.ToList(), LongToIntSafe(TotalItems) );//safty rails for virualize - doesn't overflow, but doesn't work either } + + int LongToIntSafe(long? value) => value switch + { + null => 0, + > int.MaxValue => int.MaxValue, + < int.MinValue => int.MinValue, + _ => (int)value + }; internal async Task HandleSelectedCell( TItem item, DataGridRowInfo rowInfo, DataGridColumn column ) { @@ -2730,14 +2738,15 @@ private IEnumerable FilterViewData() // only use pagination if the custom data loading is not used if ( !ManualReadMode && !Virtualize ) { - var skipElements = ( Page - 1 ) * PageSize; + long skipElements = ( Page - 1 ) * PageSize; if ( skipElements > filteredData.Count ) { Page = paginationContext.LastPage; skipElements = ( Page - 1 ) * PageSize; } - - return filteredData.Skip( skipElements ).Take( PageSize ); + + //here the conversion to int is safe, because without manualReadMode it's not probable user will use more than int.MaxValue data + return filteredData.Skip( (int)skipElements ).Take( PageSize ); } return filteredData; @@ -3225,7 +3234,7 @@ private bool IsMultiSelectAllIndeterminate /// /// This field must be set only when is used to load the data. /// - [Parameter] public int? TotalItems { get => paginationContext.TotalItems; set => paginationContext.TotalItems = value; } + [Parameter] public long? TotalItems { get => paginationContext.TotalItems; set => paginationContext.TotalItems = value; } /// /// Gets the data after all of the filters have being applied. @@ -3394,12 +3403,12 @@ public IReadOnlyList> BatchChanges /// /// Gets or sets the current page number. /// - [Parameter] public int Page { get => paginationContext.Page; set => paginationContext.Page = value; } + [Parameter] public long Page { get => paginationContext.Page; set => paginationContext.Page = value; } /// /// Occurs after the selected page has changed. /// - [Parameter] public EventCallback PageChanged { get; set; } + [Parameter] public EventCallback PageChanged { get; set; } /// /// Gets or sets content of table body for empty DisplayData. @@ -3863,7 +3872,7 @@ public IReadOnlyList> BatchChanges /// /// Gets a zero-based index of the currently selected row if found; otherwise it'll return -1. Considers the current pagination. /// - public int SelectedRowIndex + public long SelectedRowIndex { get { diff --git a/Source/Extensions/Blazorise.DataGrid/DataGridState.cs b/Source/Extensions/Blazorise.DataGrid/DataGridState.cs index 139e02a94b..a25ecb8fe5 100644 --- a/Source/Extensions/Blazorise.DataGrid/DataGridState.cs +++ b/Source/Extensions/Blazorise.DataGrid/DataGridState.cs @@ -120,7 +120,7 @@ private static string ExtractFieldName( Expression> /// /// Gets or sets the current page number. /// - public int Page { get; set; } + public long Page { get; set; } /// /// Gets or sets the maximum number of items for each page. diff --git a/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridFilteredDataEventArgs.cs b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridFilteredDataEventArgs.cs index acf8c7c55e..3f03d5fa1e 100644 --- a/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridFilteredDataEventArgs.cs +++ b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridFilteredDataEventArgs.cs @@ -17,7 +17,7 @@ public class DataGridFilteredDataEventArgs : EventArgs /// List of filtered data items. /// Number of filtered items. /// Total available items in the data-source. - public DataGridFilteredDataEventArgs( IEnumerable filteredData, int filteredItems, int totalItems ) + public DataGridFilteredDataEventArgs( IEnumerable filteredData, int filteredItems, long totalItems ) { Data = filteredData; FilteredItems = filteredItems; @@ -37,5 +37,5 @@ public DataGridFilteredDataEventArgs( IEnumerable filteredData, int filte /// /// Gets the total available items in the data-source. /// - public int TotalItems { get; } + public long TotalItems { get; } } \ No newline at end of file diff --git a/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridPageChangedEventArgs.cs b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridPageChangedEventArgs.cs new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridPageChangedEventArgs.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridReadDataEventArgs.cs b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridReadDataEventArgs.cs index 038c62dd14..ff0e581b5e 100644 --- a/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridReadDataEventArgs.cs +++ b/Source/Extensions/Blazorise.DataGrid/EventArguments/DataGridReadDataEventArgs.cs @@ -44,7 +44,7 @@ public DataGridReadDataEventArgs( DataGridReadDataMode readDataMode, IEnumerable> columns, IList> sortByColumns, - int page, + long page, int pageSize, int virtualizeOffset, int virtualizeCount, @@ -77,7 +77,7 @@ public DataGridReadDataEventArgs( /// /// Gets the requested page number. /// - public int Page { get; } + public long Page { get; } /// /// Gets the max number of items requested by page. diff --git a/Source/Extensions/Blazorise.DataGrid/Utils/ExpressionCompiler.cs b/Source/Extensions/Blazorise.DataGrid/Utils/ExpressionCompiler.cs index b452bc321b..476a798092 100644 --- a/Source/Extensions/Blazorise.DataGrid/Utils/ExpressionCompiler.cs +++ b/Source/Extensions/Blazorise.DataGrid/Utils/ExpressionCompiler.cs @@ -309,6 +309,8 @@ public static IQueryable ApplyDataGridSort( this IQueryable /// /// Applies the paging filter to the queryable data. + /// Only usable for datasets of approximately 1 million items when using virtualization. + /// Only usable for datasets up to `int.MaxValue` items when using paging. /// /// /// The Data to be queried @@ -363,6 +365,8 @@ public static IQueryable ApplyDataGridSort( this IQueryable /// /// Applies the paging filter to the queryable data. + /// Only usable for datasets of approximately 1 million items when using virtualization. + /// Only usable for datasets up to `int.MaxValue` items when using paging. /// /// /// The Data to be queried @@ -373,7 +377,7 @@ public static IQueryable ApplyDataGridPaging( this IQueryable@Localizer.Localize( ParentDataGrid.Localizers?.NumbersOfItemsLocalizer, "{0} - {1} of {2} items", curStart, curEnd, totalItems ) } } @@ -210,7 +210,7 @@ } - @for ( int i = PaginationContext.FirstVisiblePage; i <= PaginationContext.LastVisiblePage; ++i ) + @for ( long i = PaginationContext.FirstVisiblePage; i <= PaginationContext.LastVisiblePage; ++i ) { var pageNumber = i; var pageNumberString = i.ToString(); @@ -237,7 +237,7 @@ else {