При разработке интерфейсов управляемых форм часто возникает задача: после выбора значения из выпадающего списка или изменения реквизита оставить фокус на том же поле, чтобы пользователь мог продолжить непрерывный ввод текста (например, при составлении сложного адреса или описания). Однако стандартная конструкция ТекущийЭлемент = Элементы.ИмяЭлемента, размещенная внутри процедуры ПриИзменении, не дает нужного результата — платформа автоматически переносит курсор на следующий по порядку обхода элемент формы.
Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим надежные способы решения этой задачи.
Проанализируем механику работы клиентского приложения. Событие ПриИзменении поля ввода вызывается в момент фиксации нового значения (например, при нажатии клавиши Enter, Tab или клике мыши вне поля). Платформа отрабатывает назначенный обработчик, но после выхода из процедуры управление возвращается стандартному системному циклу. На этом этапе платформа выполняет завершающее действие — переводит фокус на следующий элемент формы согласно установленному порядку обхода.
Даже если внутри процедуры мы принудительно переназначим ТекущийЭлемент или попробуем переключить фокус на соседнее поле и обратно, завершающая логика платформы всё равно переопределит наш выбор и сместит курсор дальше. Чтобы удержать фокус, необходимо вмешаться в процесс на следующем такте работы клиентского интерфейса либо перехватить ввод на более раннем этапе.
Наиболее универсальное и надежное решение — использовать механизм отложенного вызова с помощью метода ПодключитьОбработчикОжидания. Мы передаем управление обратно платформе для завершения стандартного цикла перехода, а затем сразу же (через минимальный интервал времени) возвращаем фокус на нужное поле.
Рассмотрим реализацию данного подхода по шагам:
ПриИзменении подключаем клиентский обработчик ожидания с интервалом 0.1 секунды и обязательным флагом однократного выполнения Истина.ТекущийЭлемент.Посмотрим на пример программного кода в модуле формы:
&НаКлиенте
Процедура ЮрАдресКонтрагентаПриИзменении(Элемент)
// Выполняем серверную обработку введенных данных при необходимости
ЮрАдресКонтрагентаПриИзмененииНаСервере();
// Запускаем разовый обработчик для возврата фокуса
ПодключитьОбработчикОжидания("УстановитьФокусНаАдрес", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьФокусНаАдрес()
ТекущийЭлемент = Элементы.ЮрАдресКонтрагента;
КонецПроцедуры
Важный момент: интервал менее 1 секунды платформой поддерживается только при условии, что параметр Однократно установлен в значение Истина. При таком вызове фокус возвращается мгновенно и незаметно для пользователя, не создавая постоянной циклической нагрузки на клиентское приложение.
Если смещение фокуса происходит именно по нажатию клавиши Enter при вводе данных в поле, можно скорректировать поведение самой формы.
Переход на Кнопка по умолчанию.После этой настройки нажатие Enter не будет инициировать автоматический переход к следующему элементу по порядку обхода, и присвоение ТекущийЭлемент = Элементы.ИмяПоля в обработчике ПриИзменении сработает корректно:
&НаКлиенте
Процедура ЛистПриИзменении(Элемент)
ТекущийЭлемент = Элементы.Лист;
КонецПроцедуры
Если задача заключается в том, чтобы выбирать фрагменты текста из выпадающего списка и сразу же дописывать строку дальше, правильнее обрабатывать не ПриИзменении, а событие ОбработкаВыбора самого элемента формы.
Разберем программный код:
&НаКлиенте
Процедура ЮрАдресКонтрагентаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
// Отменяем стандартное поведение платформы
СтандартнаяОбработка = Ложь;
// Дополняем текущий реквизит выбранным значением
Объект.ЮрАдресКонтрагента = Строка(Объект.ЮрАдресКонтрагента) + " " + Строка(ВыбранноеЗначение);
// Обновляем отображение текста в поле ввода без потери позиции редактирования
Элемент.ОбновитьТекстРедактирования();
// Удерживаем фокус на элементе
ТекущийЭлемент = Элемент;
КонецПроцедуры
Установка СтандартнаяОбработка = Ложь предотвращает стандартный сход с элемента управления, а метод ОбновитьТекстРедактирования() синхронизирует отображаемый текст с данными реквизита объекта.
В сценариях живого ввода текста без прерывания набора можно задействовать специализированные события поля ввода:
СтандартнаяОбработка = Ложь, можно программно обработать строку. Следует учитывать, что внутри этого события нельзя выполнять синхронные контекстные серверные вызовы (директива &НаСервере), так как они приводят к принудительному завершению редактирования и потере активности поля.