Как программно вернуть фокус на элемент управляемой формы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах в 1С:Предприятии 8.3 программисты часто сталкиваются с ситуацией, когда стандартные методы управления курсором не приносят желаемого результата. Казалось бы, простая задача — вернуть фокус в поле ввода после того, как пользователь ввел некорректные данные или для обеспечения удобства потокового ввода. Однако обычное присвоение значения свойству ТекущийЭлемент внутри популярных событий (например, ПриИзменении) часто игнорируется платформой. В рамках этой статьи мы подробно разберем, почему это происходит, и изучим надежные способы решения данной задачи.

Анализируем причину проблемы: почему фокус «улетает»?

Рассмотрим стандартную ситуацию. У нас есть поле ввода ИД, и в его обработчике события ПриИзменении мы пишем код:


&НаКлиенте
Процедура ИДПриИзменении(Элемент)
    // Какая-то логика проверки
    ЭтаФорма.ТекущийЭлемент = Элементы.ИД;
КонецПроцедуры

Проанализируем, что происходит на уровне платформы. Когда пользователь нажимает Enter или Tab, находясь в поле ввода, запускается цепочка событий. Сначала отрабатывает наш программный код в ПриИзменении. В этот момент фокус действительно может формально находиться на элементе ИД. Однако после завершения выполнения процедуры ПриИзменении платформа продолжает выполнение стандартного алгоритма «перехода по элементам». Она видит, что была нажата клавиша перехода, и принудительно перемещает фокус на следующий элемент в порядке обхода. Таким образом, ваша программная установка затирается системным действием, которое происходит на миллисекунды позже.

Решение №1: Использование обработчика ожидания

Наиболее эффективным и проверенным способом «обмануть» системный порядок обхода является использование метода ПодключитьОбработчикОжидания. Суть метода заключается в том, чтобы вынести команду установки фокуса за пределы текущего стека выполнения событий платформы. Мы просим систему выполнить наш код чуть позже, когда все стандартные переходы уже завершатся.

Разберем по шагам, как это реализовать:

  1. В основном обработчике (например, ПриИзменении) мы не устанавливаем фокус напрямую, а подключаем однократный обработчик ожидания.
  2. Создаем отдельную процедуру на клиенте, которая будет выполнять саму установку фокуса.

Посмотрим на пример кода:


&НаКлиенте
Процедура ИДПриИзменении(Элемент)
    // Проверяем условие, при котором нужно вернуть фокус
    Если ДанныеНекорректны Тогда
        // Подключаем обработчик. Интервал 0.1 сек, Истина - выполнить один раз
        ПодключитьОбработчикОжидания("УстановитьФокусНаИД", 0.1, Истина);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура УстановитьФокусНаИД()
    // Теперь фокус гарантированно вернется в нужное поле
    ТекущийЭлемент = Элементы.ИД;
КонецПроцедуры

Важный нюанс: Как отмечают опытные разработчики, иногда интервала 0.1 секунды может быть недостаточно, особенно при работе в веб-клиенте или при наличии тяжелых клиентских скриптов. В таких случаях можно увеличить интервал до 0.3 или 0.5 секунды, хотя визуально это может стать заметно пользователю.

Решение №2: Визуальное выделение (УстановитьГраницыВыделения)

Иногда фокус фактически возвращается на элемент, но пользователь этого не видит: курсор не мигает или текст не выделен. Это происходит потому, что поле ввода находится не в режиме редактирования. Чтобы сделать возврат фокуса «живым», проанализируем использование метода УстановитьГраницыВыделения. Это особенно полезно для строковых полей.

Доработаем нашу процедуру установки фокуса:


&НаКлиенте
Процедура УстановитьФокусНаИД()
    ЭлементФокуса = Элементы.ИД;
    ТекущийЭлемент = ЭлементФокуса;
    
    // Выделяем весь текст в поле, чтобы пользователь мог сразу начать вводить заново
    // Либо устанавливаем курсор в конец строки
    ДлинаТекста = СтрДлина(Объект.ИД);
    ЭлементФокуса.УстановитьГраницыВыделения(0, ДлинаТекста);
КонецПроцедуры

Такой подход делает интерфейс гораздо более дружелюбным. Пользователю не нужно удалять старое (неверное) значение вручную — оно уже выделено и удалится при первом же нажатии клавиши.

Решение №3: Использование свойства «Отказ» в событиях выбора

Если ваша задача — не дать пользователю уйти из поля, пока данные не будут введены верно, стоит рассмотреть альтернативные события. В некоторых случаях вместо ПриИзменении выгоднее использовать события, имеющие параметр Отказ или СтандартнаяОбработка. Например, при работе в табличных частях это может быть ПередОкончаниемРедактирования.

Если в таком событии установить Отказ = Истина, платформа вообще не позволит завершить редактирование текущего элемента, и фокус останется на месте автоматически, без всяких «костылей» с таймерами.

Особенности установки фокуса в таблицах

Работа с фокусом в табличных частях (динамических списках или таблицах значений) требует особого внимания. Выясним причину: таблица — это сложный объект, состоящий из множества строк и колонок. Простого указания ТекущийЭлемент = Элементы.Таблица будет недостаточно — курсор встанет на саму таблицу, но не в конкретную ячейку.

Для активации конкретной ячейки необходимо выполнить два действия:

  1. Установить свойство ТекущаяСтрока у элемента формы типа «Таблица» (нужно передать идентификатор строки).
  2. Установить свойство ТекущийЭлемент самой формы, указав конкретную колонку.

Пример кода для таблицы:


&НаКлиенте
Процедура ВернутьФокусВТаблицу(ИдентификаторСтроки)
    // 1. Позиционируемся на нужной строке
    Элементы.Товары.ТекущаяСтрока = ИдентификаторСтроки;
    
    // 2. Указываем конкретную колонку (поле ввода внутри таблицы)
    ТекущийЭлемент = Элементы.ТоварыКоличество;
КонецПроцедуры

Рекомендации и предостережения

При работе с программной установкой фокуса следует помнить о нескольких критически важных моментах:

Подводя итог, можно сказать, что управление фокусом в 1С — это не только работа со свойствами элементов, но и понимание жизненного цикла событий формы. Использование ПодключитьОбработчикОжидания остается «золотым стандартом» для решения проблем с перебитием фокуса системными механизмами платформы 8.3.

← На главную