2

我希望你一切都好。我有一个小问题,我想根据另一个 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,它允许构建另一个 DropdownButton 的值,其中这次包含当前在StudyCycles Dropdown中选择的StudyCycle的ClassroomsLevels(到目前为止一切都很好)

    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,
}

谢谢你!

4

1 回答 1

4

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

if (studyCycle != null) {
 setState(() {
 // Add this line
 _selectedClassroom = null;
 _selectedStudyCycle = studyCycle;
});
}
于 2021-11-21T13:00:34.300 回答