Разработчики, создающие интерфейсы на управляемых формах в 1С, часто сталкиваются с необходимостью выполнять определенный код при изменении состояния интерфейсных элементов. Типичный пример — выполнение ресурсоемких операций (например, динамическая подгрузка связанных данных, заполнение табличных частей или отправка запросов) только тогда, когда пользователь разворачивает определенную группу на форме.
Однако при детальном изучении свойств объекта ГруппаФормы выясняется, что у него полностью отсутствуют стандартные события, связанные со свертыванием или развертыванием панели. В этой статье мы подробно разберем, почему платформа устроена именно так, как решить задачу сохранения состояния группы без написания кода и как реализовать надежные обходные пути для перехвата этого события программно.
Отсутствие встроенного события для изменения состояния группы — это осознанное архитектурное решение разработчиков платформы «1С:Предприятие». В управляемом приложении отрисовка интерфейса максимально делегирована на сторону клиента, а логика взаимодействия минимизирует лишние вызовы сервера. Если бы при каждом клике по заголовку группы инициировалось серверное событие, это приводило бы к неоправданным задержкам интерфейса (round-trips) на медленных каналах связи.
Тем не менее, решать задачу интеграции бизнес-логики со сворачиваемыми группами программистам приходится регулярно. Давайте последовательно рассмотрим несколько эффективных способов реализации этой задачи.
Прежде чем приступать к написанию программного кода, проанализируем конечную цель. Очень часто разработчикам требуется «отловить» свертывание или развертывание группы исключительно для того, чтобы запомнить ее текущее состояние. Это нужно, чтобы при следующем открытии этой же формы пользователю не приходилось заново настраивать интерфейс под себя.
Для реализации этого сценария писать программный код вообще не требуется. Платформа 1С делает это автоматически благодаря механизму сохранения настроек формы. Нам достаточно проверить и настроить свойства нашей формы:
СохранениеДанныхФормыВНастройках и установим его значение в Использовать.После этого платформа будет автоматически запоминать, в каком состоянии (свернута или развернута) пользователь оставил группу перед закрытием формы, и восстанавливать это состояние при следующем запуске. Это работает абсолютно прозрачно и не создает нагрузки на сервер. Для программного управления и применения сохраненных настроек формы среди пользователей можно использовать обработку для сохранения настроек формы для всех пользователей.
Если автоматического сохранения недостаточно и нам обязательно нужно программно анализировать состояние группы, обратим внимание на развитие платформы. Начиная с версии 8.3.12, у объекта управляемой формы типа «Обычная группа» (при условии, что ее поведение настроено как «Свертываемая» или «Всплывающая») появились штатные методы для программного контроля:
Элементы.ИмяГруппы.Скрыта() — метод возвращает булево значение: Истина, если группа свернута в данный момент, и Ложь, если развернута.Элементы.ИмяГруппы.Показать() — позволяет программно развернуть группу.Элементы.ИмяГруппы.Скрыть() — позволяет программно свернуть группу.Наличие этих методов упрощает написание обходных решений, избавляя нас от необходимости хранить состояние группы в отдельных переменных формы.
Поскольку прямого интерактивного события свертывания группа не предоставляет, мы можем полностью сымитировать поведение стандартной кнопки свертки, используя декорацию формы. Это наиболее красивый, производительный и полностью контролируемый способ.
Разберем по шагам, как это реализовать:
ОтображатьЗаголовок.ДекорацияЗаголовокГруппы.Гиперссылка в значение Истина. Зададим начальный текст, имитирующий свернутое состояние, например: «▼ Показать дополнительные параметры».Нажатие. При клике на этот элемент будет вызываться клиентский обработчик на форме.Теперь напишем лаконичный код в модуле формы, который будет управлять состоянием группы и выполнять сопутствующую логику:
&НаКлиенте
Процедура ДекорацияЗаголовокГруппыНажатие(Элемент)
// Выясняем текущее состояние группы с помощью штатного метода
ГруппаСвернута = Элементы.ГруппаДополнительно.Скрыта();
Если ГруппаСвернута Тогда
// Сначала выполняем наш произвольный код, который нужно запустить при развертывании
ВыполнитьЛогикуПриРазвертыванииГруппы();
// Разворачиваем группу программно
Элементы.ГруппаДополнительно.Показать();
// Меняем визуальный маркер заголовка на раскрытый
Элементы.ДекорацияЗаголовокГруппы.Заголовок = "▲ Скрыть дополнительные параметры";
Иначе
// Сворачиваем группу программно
Элементы.ГруппаДополнительно.Скрыть();
// Возвращаем маркер в исходное свернутое состояние
Элементы.ДекорацияЗаголовокГруппы.Заголовок = "▼ Показать дополнительные параметры";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьЛогикуПриРазвертыванииГруппы()
// Здесь располагается ваш прикладной код
// Например, оповещение пользователя или запуск фонового расчета
ПоказатьПредупреждение(, "Группа успешно развернута, запускается обработка данных!");
КонецПроцедуры
При таком подходе пользователь визуально не заметит разницы: он кликает по привычной надписи-заголовку со стрелочкой, группа мгновенно реагирует на действие, а разработчик получает полный контроль над моментом сворачивания и разворачивания без лишней нагрузки на систему.
Если по каким-то причинам менять стандартный интерфейс группы и отключать ее родной заголовок нельзя, существует альтернативный (хотя и менее производительный) способ — использование обработчика ожидания. Метод основывается на регулярном фоновом опросе состояния видимости группы.
Давайте проанализируем реализацию этого подхода. Нам потребуется хранить последнее зафиксированное состояние группы в переменной модуля управляемой формы.
В самом верху модуля формы объявим переменную:
&НаКлиенте
Переменная ПредыдущееСостояниеСкрытости;
Затем инициализируем ее при открытии формы и подключим фоновый опрос:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Фиксируем стартовое состояние группы
ПредыдущееСостояниеСкрытости = Элементы.ГруппаДополнительно.Скрыта();
// Подключаем обработчик ожидания с интервалом в 1 секунду (или меньше при необходимости)
ПодключитьОбработчикОжидания("ПроверитьСостояниеСворачиванияГруппы", 1, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСостояниеСворачиванияГруппы()
ТекущееСостояниеСкрытости = Элементы.ГруппаДополнительно.Скрыта();
// Если состояние изменилось по сравнению с предыдущей итерацией опроса
Если ТекущееСостояниеСкрытости <> ПредыдущееСостояниеСкрытости Тогда
Если Не ТекущееСостояниеСкрытости Тогда
// Группа была развернута пользователем вручную
ВыполнитьЛогикуПриРазвертыванииГруппы();
КонецЕсли;
// Обновляем значение переменной для последующего сравнения
ПредыдущееСостояниеСкрытости = ТекущееСостояниеСкрытости;
КонецЕсли;
КонецПроцедуры
Важное примечание: Этот метод следует использовать с осторожностью. Регулярный вызов кода по таймеру (даже раз в секунду) создает дополнительную микронагрузку на клиентский сеанс. Рекомендуется отдавать предпочтение Решению №3 с кастомными заголовками, так как оно работает по чисто событийной схеме и не тратит ресурсы процессора в моменты бездействия пользователя.