Flutter中SFDataGrid搭配SFDataPager分页失效问题求助
Flutter Syncfusion DataGrid 分页失效问题修复
问题核心
使用syncfusion_flutter_datagrid的SfDataPager时分页功能完全失效:
- 计算得出的
pageCount正确(15条数据分2页),但rowsPerPage配置不生效 - DataGrid仍显示全部15条数据并保持可滚动状态
- SfDataGrid和SfDataPager均已关联DataGridSource,但分页操作无任何响应
错误原因
- DataGridSource实例不共享:SfDataGrid和SfDataPager各自创建了独立的
DTRHistoryDataGridSource实例,两者数据状态完全隔离,分页器的操作无法同步到DataGrid - 缺失分页逻辑实现:自定义的
DTRHistoryDataGridSource未重写handlePageChange方法,无法响应分页器的页码切换事件 - 每页条数配置冲突:SfDataGrid设置
rowsPerPage:11,但分页器按10条一页计算,数值不统一导致分页逻辑混乱
修复步骤
- 共享DataGridSource实例:在父组件中创建唯一的
DTRHistoryDataGridSource实例,同时传递给SfDataGrid和SfDataPager - 完善分页逻辑:在
DTRHistoryDataGridSource中重写handlePageChange方法,根据页码和每页条数筛选数据并通知DataGrid刷新 - 统一每页条数:保持SfDataGrid的
rowsPerPage与分页器的计算逻辑一致
修改后的代码
1. 父视图组件修改
// 在父组件中初始化共享的DataGridSource实例 final DTRHistoryDataGridSource _dataSource = DTRHistoryDataGridSource( dtrHistoryData: _controller.historyData.value, ); // 组件渲染部分 AppDataGrid( dtrHistoryData: _controller.historyData.value, columns: _controller.columns, dataSource: _dataSource, // 传入共享实例 ), SizedBox( height: dataPagerHeight, width: double.maxFinite, child: Center( child: SfDataPager( pageCount: ((_controller.historyData.value.timeData?.length ?? 0) / 10).ceilToDouble(), delegate: _dataSource, // 使用同一个数据源实例 direction: Axis.horizontal, ), ), ),
2. AppDataGrid组件修改
import 'package:flutter/material.dart'; import 'package:puncher_app/app/global/constants/colors.dart'; import 'package:puncher_app/app/models/dtr_history_data.dart'; import 'package:syncfusion_flutter_core/theme.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import '../../data/table/history_table2_data.dart'; class AppDataGrid extends StatelessWidget { final DTRHistoryData dtrHistoryData; final List<GridColumn> columns; final DTRHistoryDataGridSource dataSource; // 添加数据源参数 const AppDataGrid({ super.key, required this.dtrHistoryData, required this.columns, required this.dataSource, // 接收共享实例 }); @override Widget build(BuildContext context) { return Expanded( child: Card( clipBehavior: Clip.antiAliasWithSaveLayer, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), color: transparent, elevation: 0, child: SfDataGridTheme( data: SfDataGridThemeData( headerColor: secondaryColor, ), child: SfDataGrid( rowsPerPage: 10, // 和分页器保持一致 verticalScrollPhysics: const ClampingScrollPhysics(), horizontalScrollPhysics: const ClampingScrollPhysics(), headerGridLinesVisibility: GridLinesVisibility.none, gridLinesVisibility: GridLinesVisibility.horizontal, source: dataSource, // 使用共享实例 columns: columns, ), ), ), ); } }
3. DTRHistoryDataGridSource修改
import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:puncher_app/app/global/constants/colors.dart'; import 'package:puncher_app/app/global/constants/styles.dart'; import 'package:puncher_app/app/global/widgets/app_text.dart'; import 'package:puncher_app/app/models/dtr_history_data.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class DTRHistoryDataGridSource extends DataGridSource { late List<DataGridRow> _dtrHistoryDataGridRows; late List<TimeData> _originalData; // 保存原始全量数据 final int _rowsPerPage = 10; // 统一每页条数 DTRHistoryDataGridSource({required DTRHistoryData dtrHistoryData}) { _originalData = dtrHistoryData.timeData ?? []; buildDataGridRows(0); // 初始化加载第一页数据 } // 根据页码构建当前页数据 void buildDataGridRows(int pageIndex) { final dateFormat = DateFormat('hh:mm a'); final startIndex = pageIndex * _rowsPerPage; final endIndex = startIndex + _rowsPerPage; final currentPageData = _originalData.sublist( startIndex, endIndex > _originalData.length ? _originalData.length : endIndex, ); _dtrHistoryDataGridRows = currentPageData .map<DataGridRow>( (timeData) => DataGridRow( cells: [ DataGridCell<String>( columnName: 'Date', value: timeData.date, ), DataGridCell<String>( columnName: 'Time In', value: timeData.timeIn?.isNotEmpty == true ? dateFormat.format(DateTime.parse(timeData.timeIn!)) : '--', ), DataGridCell<String>( columnName: 'Time Out', value: timeData.timeOut?.isNotEmpty == true ? dateFormat.format(DateTime.parse(timeData.timeOut!)) : '--', ), DataGridCell<String>( columnName: 'Duration', value: timeData.duration != null ? formatDuration(timeData.duration!) : '--', ) ], ), ) .toList(); } String formatDuration(String duration) { final parts = duration.split(' '); final hours = parts[0]; final minutes = parts[2]; return '${hours}h${minutes}m'; } @override List<DataGridRow> get rows => _dtrHistoryDataGridRows; @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map<Widget>((dataGridCell) { return Container( alignment: Alignment.center, child: AppText( text: dataGridCell.value.toString(), textColor: secondaryColor, style: kRegTextBlack, alignment: TextAlign.center, )); }).toList()); } @override Object getValue(int rowIndex, String columnName) { final TimeData timeData = _originalData[rowIndex]; switch (columnName) { case 'Date': return timeData.date!; case 'Time In': return timeData.timeIn!; case 'Time Out': return timeData.timeOut!; case 'Duration': return timeData.duration!; default: return ''; } } // 重写分页切换方法,响应SfDataPager的页码变化 @override Future<void> handlePageChange(int oldPageIndex, int newPageIndex) async { buildDataGridRows(newPageIndex); notifyListeners(); // 通知DataGrid刷新当前页数据 return super.handlePageChange(oldPageIndex, newPageIndex); } }
内容的提问来源于stack exchange,提问作者Richard Johnson
相关产品推荐
相关产品推荐

