简体   繁体   English

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

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

I hope you are well.我希望你一切都好。 I have a little problem, I would like to dynamically change the value of a DropdownButton based on the value of another DropdownButton.我有一个小问题,我想根据另一个 DropdownButton 的值动态改变一个 DropdownButton 的值。

Well, I'll explain where I'm at and what the problem is:好吧,我将解释我在哪里以及问题是什么:

First I have a list of StudyCycle containing 3 elements;首先,我有一个包含 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,
    ])
  ];

This StudyCycle list is used to build the first DropdownButton这个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);
            }
          },
        )

And by selecting a StudyCycle from the StudyCycles Dropdown , it allows to build values of another DropdownButton containing this time the ClassroomsLevels of the StudyCycle currently selected in the StudyCycles Dropdown (so far so good)通过从StudyCycles Dropdown中选择一个StudyCycle ,它允许构建另一个 DropdownButton 的值,其中这次包含当前在StudyCycles Dropdown中选择的StudyCycleClassroomsLevels (到目前为止一切都很好)

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

The problem occurs when a ClassroomLevel is selected and I change StudyCycle , I get this error:选择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'

I tried my best to solve the problem but I couldn't (and I don't really understand why), so I am relying on you.我尽力解决了这个问题,但我不能(而且我真的不明白为什么),所以我依靠你。 Can you help me to understand what the error is and how to solve it?您能帮我了解错误是什么以及如何解决吗?

The complete code完整的代码

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

THANK YOU!谢谢你!

The reason for the error is that the value of _selectedClassroom in your second dropdown is not present in the new classroom list _selectedStudyCycle..classrooms once you change the value of the first dropdown.错误的原因是,在您更改第一个下拉列表的值后,新教室列表_selectedClassroom中不存在第二个下拉列表中的_selectedStudyCycle..classrooms值。 Simply reset the value of your second dropdown in the setState method:只需在setState方法中重置第二个下拉列表的值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM