Руководство / Контролы и формы

Значение принадлежит приложению, а не полю ввода.

Контролы LumaFlow управляются явным State. UI Toolkit сохраняет нативный фокус и клавиатурное поведение, а приложение остаётся единственным источником данных.

Один State — один источник истины.

Поле отображает текущее значение State. Ввод пользователя обновляет State. Изменение State из кода обновляет поле без имитации пользовательского события.

ProjectForm.cs
private readonly State<string> _name = new("");

new TextField(
  _name,
  label: "Название проекта",
  placeholder: "Введите название",
  onChanged: value => SaveDraft(value));

Программное обновление не вызывает onChanged повторно.

Это предотвращает цикл «State изменил control → control снова записал State». Callback обозначает действие пользователя, а не любое визуальное обновление.

Не храните вторую копию значения.

Если одновременно поддерживать поле класса и State, они разойдутся. Domain model можно обновлять в callback, но отображаемое значение должно иметь одного владельца.

Валидация тоже является состоянием.

FormState координирует поля, а FormField<T> хранит значение и результат проверки. При submit сначала проверьте форму и только потом отправляйте данные.

Не перестраивайте дерево ради сброса формы.

Сбросьте значения и ошибки через владельца формы. Rebuild описывает интерфейс заново, но не решает, какие данные продукта удалить.

Используйте нативное клавиатурное поведение.

Встроенные контролы уже участвуют в focus ring UI Toolkit. Не заменяйте их визуальным Container с callback, если элемент должен работать с Tab, Enter или экранным диктором.

Для программного перехода храните FocusNode у владельца экрана. Не создавайте его внутри Build.

Сначала ThemeData, затем точечные отличия.

Тема содержит общие стили компонентов. Локальный style переопределяет только явно заданные свойства.

ApplicationTheme.cs
new Theme(
  theme,
  new Button(
    "Сохранить проект", Save,
    ButtonVariant.Primary));
Дальше: доступность и локализация →