根据另一个 DropdownButton [FLUTTER] 的值动态更改 DropdownButton 的值

Dynamically change the value of a DropdownButton based on the value of another DropdownButton [FLUTTER]

希望你一切都好。 我有一个小问题,我想根据另一个 DropdownButton 的值动态更改一个 DropdownButton 的值。

好吧,我会解释我的位置和问题所在:

首先我有一个包含 3 个元素的 StudyCycle 列表;

final _studyCycles = const <StudyCycle>[
    StudyCycle(cycle: Cycles.elementary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.cp,
      ClassroomsLevels.ce1,
      ClassroomsLevels.ce2,
      ClassroomsLevels.cm1,
      ClassroomsLevels.cm2,
    ]),
    StudyCycle(cycle: Cycles.primary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.sixth,
      ClassroomsLevels.fifth,
      ClassroomsLevels.fourth,
      ClassroomsLevels.third,
    ]),
    StudyCycle(cycle: Cycles.secondary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.second,
      ClassroomsLevels.first,
      ClassroomsLevels.terminal,
    ])
  ];

这个StudyCycle列表用于构建第一个DropdownButton

 DropdownButton<StudyCycle>(
          value: _selectedStudyCycle,
          items: List<DropdownMenuItem<StudyCycle>>.generate(
            _studyCycles.length,
            (index) => DropdownMenuItem<StudyCycle>(
              value: _studyCycles[index],
              child: Text(_studyCycles[index].cycle.toString()),
            ),
          ),
          hint: const Text('Your Study Cycle'),
          onChanged: (StudyCycle? studyCycle) {
            if (studyCycle != _selectedStudyCycle) {
              if (_selectedStudyCycle != null) setState(() => _selectedStudyCycle = null);

              if (studyCycle != null) setState(() => _selectedStudyCycle = studyCycle);
            }
          },
        )

并且通过从 StudyCycles Dropdown 中选择一个 StudyCycle,它允许构建另一个包含这次 [=34] 的 DropdownButton 的值=]ClassroomsLevels 的 StudyCycle 当前在 StudyCycles 下拉菜单 中选择(到目前为止还不错)

    DropdownButton<ClassroomsLevels>(
      hint: const Text('Select your classroom'),
      value: _selectedClassroom,
      items: _selectedStudyCycle == null
          ? []
          : List<DropdownMenuItem<ClassroomsLevels>>.generate(
              _selectedStudyCycle!.classrooms.length,
              (index) => DropdownMenuItem<ClassroomsLevels>(
                value: _selectedStudyCycle!.classrooms[index],
                child: Text(_selectedStudyCycle!.classrooms[index].toString()),
              ),
            ),
      onChanged: (ClassroomsLevels? classroom) => setState(() => _selectedClassroom = classroom),
    )

选择 ClassroomLevel 并更改 StudyCycle 时出现问题,我收到此错误:

There should be exactly one item with [DropdownButton]'s value: ClassroomsLevels.fourth. 
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 915 pos 15: 'items == null || items.isEmpty || value == null ||
              items.where((DropdownMenuItem<T> item) {
                return item.value == value;
              }).length == 1'

我尽力解决了这个问题,但我不能(而且我真的不明白为什么),所以我依靠你。 你能帮我了解错误是什么以及如何解决吗?

完整代码

import 'package:flutter/material.dart';

class MyHomePage2 extends StatefulWidget {
  const MyHomePage2({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage2> createState() => _MyHomePage2State();
}

class _MyHomePage2State extends State<MyHomePage2> {
  final _studyCycles = const <StudyCycle>[
    StudyCycle(cycle: Cycles.elementary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.cp,
      ClassroomsLevels.ce1,
      ClassroomsLevels.ce2,
      ClassroomsLevels.cm1,
      ClassroomsLevels.cm2,
    ]),
    StudyCycle(cycle: Cycles.primary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.sixth,
      ClassroomsLevels.fifth,
      ClassroomsLevels.fourth,
      ClassroomsLevels.third,
    ]),
    StudyCycle(cycle: Cycles.secondary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.second,
      ClassroomsLevels.first,
      ClassroomsLevels.terminal,
    ])
  ];

  StudyCycle? _selectedStudyCycle;

  ClassroomsLevels? _selectedClassroom;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            DropdownButton<StudyCycle>(
              value: _selectedStudyCycle,
              items: List<DropdownMenuItem<StudyCycle>>.generate(
                _studyCycles.length,
                (index) => DropdownMenuItem<StudyCycle>(
                  value: _studyCycles[index],
                  child: Text(_studyCycles[index].cycle.toString()),
                ),
              ),
              hint: const Text('Your Study Cycle'),
              onChanged: (StudyCycle? studyCycle) {
                if (studyCycle != _selectedStudyCycle) {
                  if (_selectedStudyCycle != null) setState(() => _selectedStudyCycle = null);

                  if (studyCycle != null) setState(() => _selectedStudyCycle = studyCycle);
                }
              },
            ),

            //

            DropdownButton<ClassroomsLevels>(
              hint: const Text('Select your classroom'),
              value: _selectedClassroom,
              items: _selectedStudyCycle == null
                  ? []
                  : List<DropdownMenuItem<ClassroomsLevels>>.generate(
                      _selectedStudyCycle!.classrooms.length,
                      (index) => DropdownMenuItem<ClassroomsLevels>(
                        value: _selectedStudyCycle!.classrooms[index],
                        child: Text(_selectedStudyCycle!.classrooms[index].toString()),
                      ),
                    ),
              onChanged: (ClassroomsLevels? classroom) => setState(() => _selectedClassroom = classroom),
            ),
          ],
        ),
      ),
    );
  }
}

class StudyCycle {
  final Cycles cycle;

  final List<ClassroomsLevels> classrooms;

  final String? description;

  final int? iconCodePoint;

  const StudyCycle({
    required this.cycle,
    required this.classrooms,
    this.description,
    this.iconCodePoint,
  });
}

enum Cycles { elementary, primary, secondary, secondaryTechnique }

enum ClassroomsLevels {
  cp,
  ce1,
  ce2,
  cm1,
  cm2,
  sixth,
  fifth,
  fourth,
  third,
  second,
  first,
  terminal,
  mechanical,
  electronic,
  electricity,
  inEngineering,
  secretariat,
  accounting,
  economy,
  agr1,
  agr2,
  agr3,
}

谢谢!

错误的原因是,在您更改第一个下拉列表的值后,第二个下拉列表中 _selectedClassroom 的值不会出现在新教室列表 _selectedStudyCycle!.classrooms 中。只需在 setState 方法中重置第二个下拉列表的值:

if (studyCycle != null) {
 setState(() {
 // Add this line
 _selectedClassroom = null;
 _selectedStudyCycle = studyCycle;
});
}