Flutter SfDataGrid:点击行跳转详情页并传递数据的实现咨询
实现Flutter SfDataGrid点击跳转详情页并传递数据
需求背景
原本已实现SfDataGrid点击行通过AlertBox展示详情,现需改为点击行后导航至独立详情页面,并传递该行数据到详情页展示。
实现步骤
创建详情页面组件
新建EmployeeDetailPage,通过构造函数接收Employee对象,在页面中直接展示该对象的各项属性。修改行点击事件逻辑
替换原onCellTap中的弹窗代码,使用Navigator.push跳转到详情页,直接从数据源的_employees列表中获取选中的Employee实例(比从row.getCells取值更直观且不易出错)。配置路由跳转
利用Flutter的MaterialPageRoute完成页面跳转,并将选中的Employee对象作为参数传递给详情页。
完整代码实现
import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; void main() { runApp(MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const SfDataGridDemo())); } class SfDataGridDemo extends StatefulWidget { const SfDataGridDemo({Key? key}) : super(key: key); @override SfDataGridDemoState createState() => SfDataGridDemoState(); } class SfDataGridDemoState extends State<SfDataGridDemo> { late EmployeeDataSource _employeeDataSource; List<Employee> _employees = <Employee>[]; @override void initState() { super.initState(); _employees = getEmployeeData(); _employeeDataSource = EmployeeDataSource(_employees); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter SfDataGrid'), ), body: SfDataGrid( source: _employeeDataSource, columns: getColumns, columnWidthMode: ColumnWidthMode.fill, onCellTap: ((details) { if (details.rowColumnIndex.rowIndex != 0) { // 获取选中的Employee实例 int selectedRowIndex = details.rowColumnIndex.rowIndex - 1; Employee selectedEmployee = _employees[selectedRowIndex]; // 跳转到详情页并传递数据 Navigator.push( context, MaterialPageRoute( builder: (context) => EmployeeDetailPage(employee: selectedEmployee), ), ); } }))); } List<GridColumn> get getColumns { return [ GridColumn( columnName: 'id', label: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.center, child: const Text( 'ID', overflow: TextOverflow.ellipsis, ))), GridColumn( columnName: 'name', label: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.center, child: const Text('Name', overflow: TextOverflow.ellipsis))), GridColumn( columnName: 'designation', label: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.center, child: const Text('Designation', overflow: TextOverflow.ellipsis))), GridColumn( columnName: 'salary', label: Container( padding: const EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.center, child: const Text('Salary', overflow: TextOverflow.ellipsis))) ]; } List<Employee> getEmployeeData() { return [ Employee(10001, 'James', 'Project Lead', 70000), Employee(10002, 'Kathryn', 'Manager', 99000), Employee(10003, 'Lara', 'Developer', 33000), Employee(10004, 'Michael', 'Designer', 35000), Employee(10005, 'Martin', 'Developer', 45000), Employee(10006, 'Newberry', 'Developer', 29000), Employee(10007, 'Balnc', 'Designer', 33000), Employee(10008, 'Perry', 'Developer', 31000), Employee(10009, 'Gable', 'Developer', 29500), Employee(10010, 'Grimes', 'Developer', 28000) ]; } } class EmployeeDataSource extends DataGridSource { EmployeeDataSource(List<Employee> employees) { buildDataGridRow(employees); } void buildDataGridRow(List<Employee> employeeData) { dataGridRow = employeeData.map<DataGridRow>((employee) { return DataGridRow(cells: [ DataGridCell<int>(columnName: 'id', value: employee.id), DataGridCell<String>(columnName: 'name', value: employee.name), DataGridCell<String>( columnName: 'designation', value: employee.designation), DataGridCell<int>(columnName: 'salary', value: employee.salary), ]); }).toList(); } List<DataGridRow> dataGridRow = <DataGridRow>[]; @override List<DataGridRow> get rows => dataGridRow.isEmpty ? [] : dataGridRow; @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map<Widget>((dataGridCell) { return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text(dataGridCell.value.toString()), ); }).toList()); } } class Employee { Employee(this.id, this.name, this.designation, this.salary); final int id; final String name; final String designation; final int salary; } // 新增详情页面组件 class EmployeeDetailPage extends StatelessWidget { final Employee employee; const EmployeeDetailPage({Key? key, required this.employee}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Employee Detail: ${employee.name}'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('ID: ${employee.id}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 12), Text('Name: ${employee.name}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 12), Text('Designation: ${employee.designation}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 12), Text('Salary: \$${employee.salary}', style: const TextStyle(fontSize: 18)), const SizedBox(height: 24), ElevatedButton( onPressed: () => Navigator.pop(context), child: const Text('Back to List'), ), ], ), ), ); } }
关键说明
- 直接从
_employees列表中取选中的实例,避免了从row.getCells逐个取值的繁琐,同时保证数据一致性。 - 详情页通过构造函数接收
Employee对象,直接使用其属性展示数据,逻辑清晰。 - 使用
Navigator.push配合MaterialPageRoute完成标准的页面跳转,符合Flutter路由规范。
内容的提问来源于stack exchange,提问作者Bhumika
相关产品推荐
相关产品推荐

