Разберем типичную практическую задачу при разработке пошаговых мастеров (мастеров заполнения, помощников) на управляемых формах 1С. Нередко возникает ситуация: разработчик создает на форме кнопку навигации «Далее», которая программно переключает страницы формы. При этом требуется, чтобы фокус ввода (курсор) оставался на кнопке «Далее» либо возвращался на нее, чтобы пользователь мог комфортно продолжить переход нажатием клавиши на клавиатуре.
Однако при установке свойства ЭтаФорма.ТекущийЭлемент = Элементы.Далее; непосредственно внутри процедуры перехода между страницами курсор упорно отказывается оставаться на кнопке и сбрасывается на элементы отображаемой страницы. При этом, если вызвать ту же самую строку кода из других событий (например, при переключении флажка), фокус устанавливается корректно. Выясним причину такого поведения платформы 1С и рассмотрим надежные способы решения этой проблемы.
Проанализируем механику работы управляемого интерфейса платформы «1С:Предприятие 8.3». Когда в обработчике команды кнопки происходит переключение страницы (изменяется свойство ТекущаяСтраница группы страниц), запускается внутренний сценарий перерисовки интерфейса клиентского приложения.
В конце текущего клиентского такта платформа принудительно активизирует первый доступный элемент на новой отображенной странице в соответствии с установленным порядком обхода. Поэтому, даже если мы в коде явно указали ЭтаФорма.ТекущийЭлемент = Элементы.Далее, платформа после завершения процедуры перезаписывает значение свойства ТекущийЭлемент, передавая фокус на дочерний элемент открывшейся страницы.
В ситуации с изменением обычного флажка (событие ПриИзменении) смена страниц не происходит, поэтому платформа не инициирует внутренний перенос фокуса, и присвоенное значение сохраняется.
На форумах часто предлагают привязать код установки фокуса к событию ПриСменеСтраницы у группы страниц через метод УстановитьДействие:
Элементы.ГруппаСтраницы.УстановитьДействие("ПриСменеСтраницы", "ПриСменеСтраницы");
&НаКлиенте
Процедура ПриСменеСтраницы(Элемент)
ЭтаФорма.ТекущийЭлемент = Элементы.Далее;
КонецПроцедуры
Однако здесь кроется важное платформенное ограничение: событие ПриСменеСтраницы вызывается исключительно при интерактивном переключении вкладок пользователем (при физическом щелчке мышью по закладке). Если же свойство ТекущаяСтраница меняется программно в коде команды «Далее», событие ПриСменеСтраницы платформой не генерируется и обработчик попросту не сработает.
Рассмотрим наиболее надежный и проверенный способ обхода автоматического поведения платформы. Нам необходимо передать фокус кнопке не в том же клиентском такте, где меняется страница, а сразу после того, как платформа завершит отображение страницы и закончит внутренний перенос курсора.
Для этого применим метод ПодключитьОбработчикОжидания с однократным вызовом и минимальной задержкой. Разберем по шагам реализацию в модуле формы:
Посмотрим на пример программного кода:
&НаКлиенте
Процедура КомандаДалее(Команда)
// Переключаем текущую страницу формы
Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.Страница2;
// Подключаем однократный обработчик на следующий такт работы клиента
ПодключитьОбработчикОжидания("УстановитьФокусНаКнопку", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьФокусНаКнопку()
// Платформа уже завершила рендеринг страницы, активизируем кнопку
ЭтаФорма.ТекущийЭлемент = Элементы.Далее;
КонецПроцедуры
При таком подходе платформа сначала полностью завершает отрисовку интерфейса и установку курсора по умолчанию, а затем управление передается процедуре УстановитьФокусНаКнопку, которая гарантированно активизирует нужную нам кнопку «Далее».
Если задача удержания фокуса на кнопке «Далее» сводится к тому, чтобы пользователь мог переходить по шагам мастера нажатием клавиши Enter, можно обойтись без принудительной передачи курсора.
Для этого в свойствах кнопки на форме или программно задаем свойство КнопкаПоУмолчанию = Истина:
Элементы.Далее.КнопкаПоУмолчанию = Истина;
В этом случае кнопка получает специальное визуальное выделение, и нажатие клавиши Enter будет вызывать команду этой кнопки независимо от того, на каком поле ввода текущей страницы находится курсор (за исключением многострочных текстовых полей).
Дополнительно проанализируем параметры самой кнопки. Если даже при использовании обработчика ожидания фокус не задерживается на элементе, обязательно проверьте следующие свойства:
Видимость и Доступность кнопки должны иметь значение Истина.ПропускатьПриОбходе должно быть установлено в значение Ложь. Если для элемента включен пропуск при обходе, платформа не позволит стабильно зафиксировать на нем фокус ввода.