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