【问题标题】:Why Flutter SfDataGrid sorting just renders sorted rows and no changes in datasource?为什么 Flutter SfDataGrid 排序只渲染排序后的行而数据源没有变化?
【发布时间】:2022-12-20 15:06:30
【问题描述】:

我正在尝试在我的 SfDataGrid 中使用内置排序。它工作正常并且颤动重新渲染并向我显示排序的表格,但是当我试图在表格中获取单元格值时它给我带来了单元格的过去(未排序)值。

所以我不仅要渲染排序后的列表,还要对数据源进行排序。

 return FutureBuilder(
    future: _portfolioDataSource.loadAndBuildPortfolioData(),
    builder: (ctx, snapshot) {
      asyncSnapshotErrorHandler(snapshot);
      if (snapshot.connectionState == ConnectionState.done) {
        return SfDataGridTheme(
            data: SfDataGridThemeData(
                headerColor: Color.fromRGBO(243, 243, 250, 1)),
            child: SfDataGrid(
                onSelectionChanged: _portfolioDataSource.isEntitiesEmpty
                    ? null
                    : _onSelectionChanged,
                gridLinesVisibility: GridLinesVisibility.horizontal,
                headerGridLinesVisibility: GridLinesVisibility.horizontal,
                highlightRowOnHover: true,
                source: _portfolioDataSource,
                frozenColumnsCount: _portfolioDataSource.isEntitiesEmpty
                    ? 0
                    : widget.frozenColumnsCount,
                columnWidthMode: ColumnWidthMode.none,
                allowPullToRefresh: true,
                allowSorting: false,
                allowMultiColumnSorting: false,
                showSortNumbers: true,
                loadMoreViewBuilder:
                    (BuildContext context, LoadMoreRows loadMoreRows) {
                  bool showIndicator = false;
                  return StatefulBuilder(builder:
                      (BuildContext context, StateSetter setState) {
                    if (showIndicator) {
                      return Container(
                          height: 60.0,
                          width: double.infinity,
                          alignment: Alignment.center,
                          decoration: BoxDecoration(
                              color: Colors.white,
                              border: BorderDirectional(
                                  top: BorderSide(
                                      width: 1.0,
                                      color:
                                          Color.fromRGBO(0, 0, 0, 0.26)))),
                          child: CircularProgressIndicator(
                              valueColor: AlwaysStoppedAnimation(
                            Color.fromRGBO(18, 183, 106, 1),
                          )));
                    } else {
                      return Container(
                          height: 60.0,
                          width: double.infinity,
                          alignment: Alignment.center,
                          decoration: BoxDecoration(
                              color: Colors.white,
                              border: BorderDirectional(
                                  top: BorderSide(
                                      width: 1.0,
                                      color:
                                          Color.fromRGBO(0, 0, 0, 0.26)))),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Container(
                                  margin:
                                      EdgeInsets.symmetric(horizontal: 20),
                                  height: 36.0,
                                  width: 142.0,
                                  child: TextButton(
                                      style: ButtonStyle(
                                          backgroundColor:
                                              MaterialStateProperty.all(
                                        Color.fromRGBO(18, 183, 106, 1),
                                      )),
                                      child: Text('LOAD MORE',
                                          style: TextStyle(
                                              color: Colors.white)),
                                      onPressed: () async {
                                        _onSelectionChanged([], []);
                                        if (context is StatefulElement &&
                                            context.state.mounted) {
                                          setState(() {
                                            print(
                                                widget.selectedInstanceIds);
                                            showIndicator = true;
                                          });
                                        }
                                        await loadMoreRows();
                                        if (context is StatefulElement &&
                                            context.state.mounted) {
                                          setState(() {
                                            showIndicator = false;
                                          });
                                        }
                                      })),
                              Container(
                                  margin:
                                      EdgeInsets.symmetric(horizontal: 20),
                                  height: 36.0,
                                  width: 142.0,
                                  child: TextButton(
                                      style: ButtonStyle(
                                          backgroundColor:
                                              MaterialStateProperty.all(
                                        Color.fromRGBO(18, 183, 106, 1),
                                      )),
                                      child: Text('LOAD ALL',
                                          style: TextStyle(
                                              color: Colors.white)),
                                      onPressed: () async {
                                        if (context is StatefulElement &&
                                            context.state.mounted) {
                                          setState(() {
                                            showIndicator = true;
                                          });
                                        }
                                        await _portfolioDataSource
                                            .loadAllRows();

                                        if (context is StatefulElement &&
                                            context.state.mounted) {
                                          setState(() {
                                            showIndicator = false;
                                          });
                                        }
                                      })),
                            ],
                          ));
                    }
                  });
                },

和数据源

    import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:zwe_spmis_mobile/models/controls/portfolio-control/portfolio_configs.dart';
import 'package:zwe_spmis_mobile/services/portfolio_service.dart';
import '../../../services/api/entity_search_service.dart';
import '../../../services/provider/service_provider.dart';
import '../../../utils/entity_helpers/filter/filter_builder.dart';
import '../../../zwe_icons_icons.dart';
import '../../entity.dart';
import '../../portfolio_items_state.dart';

class PortfolioDataSource extends DataGridSource {
  final List<dynamic> _entities = [];
  List<int> downloadedItemIds = [];
  List<DataGridRow> _dataGridRows = [];
  PortfolioService _portfolioService = new PortfolioService();
  PortfolioItemsState _portfolioItemsState;
  final FilterBuilder _filter;
  final String _categorySystemName;
  final Function buildDataGridRows;
  final highlitedFieldSystemName;
  String? bulkAction;
  int pageNumber = 0;
  int countPerPage = 20;
  String sortFields = "DateUpdated";
  bool isEntitiesEmpty = false;
  EntitySearchService _offlineEntitySearchService =
      ServiceProvider.getOfflineContext().getEntitySearchService();

  PortfolioDataSource(
      this._portfolioItemsState,
      this._filter,
      this._categorySystemName,
      this.buildDataGridRows,
      this.highlitedFieldSystemName,
      this.countPerPage,
      this.pageNumber,
      {this.bulkAction: null});

  Future<void> handleLoadMoreRows() async {
    this.pageNumber++;
    await loadMoreAndBuildPortfolioData();
  }

  Future<void> loadAllRows() async {
    this.pageNumber = 0;
    this.countPerPage = 500;
    await loadAndBuildPortfolioData();
    this.pageNumber = 25;
    this.countPerPage = 20;
  }

  @override
  List<DataGridRow> get rows => _dataGridRows;

  @override
  DataGridRowAdapter? buildRow(DataGridRow row) {
    TextStyle? getTextStyle(DataGridCell<dynamic> dataGridCell) {
      return TextStyle(
          color: dataGridCell.columnName == ''
              ? Color.fromRGBO(19, 180, 105, 1)
              : null);
    }

    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      return Container(
          alignment: (dataGridCell.columnName == 'id')
              ? Alignment.centerRight
              : Alignment.centerLeft,
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: dataGridCell.columnName == 'actions'
              ? RichText(
                  text: TextSpan(
                    children: [
                      WidgetSpan(
                          child: (dataGridCell.value.toString() == 'Download')
                              ? Icon(
                                  ZweIcons.download,
                                  size: 20,
                                  color: Color.fromRGBO(19, 180, 105, 1),
                                )
                              : (dataGridCell.value.toString() == 'Submit')
                                  ? RichText(
                                      text: TextSpan(
                                        style: TextStyle(
                                            color:
                                                Color.fromRGBO(19, 180, 105, 1),
                                            fontWeight: FontWeight.w900),
                                        children: [
                                          WidgetSpan(
                                            child: Icon(
                                              Icons.upload,
                                              size: 20,
                                              color: Color.fromRGBO(
                                                  19, 180, 105, 1),
                                            ),
                                          ),
                                        ],
                                      ),
                                    )
                                  : Text('')),
                      TextSpan(
                        style: dataGridCell.value.toString() == 'Downloaded' ||
                                dataGridCell.value.toString() == 'Delete'
                            ? TextStyle(
                                color: Color.fromRGBO(19, 180, 105, 1),
                                fontWeight: FontWeight.w900)
                            : TextStyle(color: Color.fromRGBO(19, 180, 105, 1)),
                        text: dataGridCell.value.toString(),
                      ),
                    ],
                  ),
                )
              : dataGridCell.columnName == 'sync'
                  ? RichText(
                      text: TextSpan(
                        children: [
                          WidgetSpan(
                            child: Icon(
                              Icons.upload,
                              size: 20,
                              color: Color.fromRGBO(19, 180, 105, 1),
                            ),
                          ),
                          TextSpan(
                            style: TextStyle(
                                color: Color.fromRGBO(19, 180, 105, 1)),
                            text: "Submit",
                          ),
                        ],
                      ),
                    )
                  : Text(
                      dataGridCell.value.toString(),
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(
                          color: dataGridCell.columnName ==
                                  this.highlitedFieldSystemName
                              ? Color.fromRGBO(44, 121, 231, 1)
                              : dataGridCell.columnName == 'actions'
                                  ? Color.fromRGBO(19, 180, 105, 1)
                                  : null),
                    ));
    }).toList());
  }

  addItem(Entity ent, String? bulkAction) {
    _entities.add(ent);
    _dataGridRows = buildDataGridRows(_entities, bulkAction);
    notifyListeners();
  }

  Future<List<int>> loadDownloadedItemIds() {
    return _offlineEntitySearchService.loadAllEntityIds(_categorySystemName);
  }

  removeItem(int entityInstanceId) {
    this.downloadedItemIds.remove(entityInstanceId);
    this
        ._entities
        .removeWhere((element) => element['instanceId'] == entityInstanceId);
    _dataGridRows.removeWhere((element) =>
        element.getCells()[element.getCells().length - 1].value ==
        entityInstanceId);
  }

  Future<List<Map<String, dynamic>>> loadCreatedItems() {
    return _offlineEntitySearchService.loadEntitiesByInstanceIds(
        this._categorySystemName,
        downloadedItemIds.where((element) => element < 0).toList());
  }

 
  Future<void> loadAndBuildPortfolioData() async {
    _entities.length = 0;
    _entities.addAll(await loadCreatedItems());
    this.downloadedItemIds = await loadDownloadedItemIds();
    if (this.bulkAction == 'Download') {
      _portfolioItemsState = PortfolioItemsState.NOT_DOWNLOADED;
    }
    await _portfolioService
        .loadEntitiesByFilter(
            _categorySystemName,
            _portfolioItemsState,
            sortFields,
            countPerPage,
            pageNumber,
            _filter,
            serializationFields[_categorySystemName])
        .then((List<dynamic> value) {
      _entities.addAll(value);
        _dataGridRows =
            buildDataGridRows(_entities, downloadedItemIds, bulkAction);
        isEntitiesEmpty = (_entities.length == 0);
        notifyListeners();
    });
  }
}

【问题讨论】:

  • 您好,请附上您需要的一些代码/预期结果好吗?

标签: flutter dart sorting sfdatagrid


【解决方案1】:

您可以从DataGridSource.effectiveRows财产。如果在 DataGrid 中应用排序,它会保存排序后的集合。

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  List<Employee> _employees = <Employee>[];
  late EmployeeDataSource _employeeDataSource;

  @override
  void initState() {
    super.initState();
    _employees = _getEmployeeData();
    _employeeDataSource = EmployeeDataSource(employeeData: _employees);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter DataGrid')),
      body: Column(
        children: [
          Container(
            margin: const EdgeInsets.all(30),
            child: ElevatedButton(
                onPressed: (() {
                  // You can get a sorted collection from effectiveRows property.
                  for (var details in _employeeDataSource.effectiveRows) {
                    print(details.getCells()[0].value);
                  }
                }),
                child: const Text('Get Sorted Collection')),
          ),
          Expanded(
            child: SfDataGrid(
              source: _employeeDataSource,
              allowSorting: true,
              columnWidthMode: ColumnWidthMode.fill,
              columns: <GridColumn>[
                GridColumn(
                    columnName: 'ID',
                    label: Container(
                        padding: const EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: const Text('ID'))),
                GridColumn(
                    columnName: 'Name',
                    label: Container(
                        padding: const EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: const Text('Name'))),
                GridColumn(
                    columnName: 'Designation',
                    label: Container(
                        padding: const EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: const Text('Designation'))),
                GridColumn(
                    columnName: 'Salary',
                    label: Container(
                        padding: const EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: const Text('Salary'))),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource({required List<Employee> employeeData}) {
    _employeeData = employeeData
        .map<DataGridRow>((Employee e) => DataGridRow(cells: <DataGridCell>[
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<int>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  List<DataGridRow> _employeeData = <DataGridRow>[];

  @override
  List<DataGridRow> get rows => _employeeData;

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((DataGridCell cell) {
      return Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.all(8.0),
        child: Text(cell.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;
}

List<Employee> _getEmployeeData() {
  return <Employee>[
    Employee(10001, 'James', 'Manager', 90000),
    Employee(10002, 'Kathryn', 'Project Lead', 75000),
    Employee(10003, 'Lara', 'Developer', 45000),
    Employee(10004, 'Michael', 'Designer', 37000),
    Employee(10005, 'Martin', 'Developer', 43000),
  ];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多