You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter SfDataGrid:点击行跳转详情页并传递数据的实现咨询

实现Flutter SfDataGrid点击跳转详情页并传递数据

需求背景

原本已实现SfDataGrid点击行通过AlertBox展示详情,现需改为点击行后导航至独立详情页面,并传递该行数据到详情页展示。

实现步骤

  1. 创建详情页面组件
    新建EmployeeDetailPage,通过构造函数接收Employee对象,在页面中直接展示该对象的各项属性。

  2. 修改行点击事件逻辑
    替换原onCellTap中的弹窗代码,使用Navigator.push跳转到详情页,直接从数据源的_employees列表中获取选中的Employee实例(比从row.getCells取值更直观且不易出错)。

  3. 配置路由跳转
    利用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 17:31:58