Почему зависает форма при смене картинки кнопки в 1С 8.3 и как это исправить?

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

При разработке пользовательских интерфейсов в управляемом приложении 1С часто возникает задача создать собственную панель навигации с кнопками-переключателями. Типичный сценарий: на форме расположено несколько кнопок, при нажатии на одну из них меняется ее иконка на активную, а на форме переключается страница панели. Однако на практике такой код может вызывать ощутимые задержки и подвисания интерфейса.

Разберем детально, почему прямое изменение картинки кнопки приводит к падению производительности и какими способами можно реализовать быструю и отзывчивую панель навигации.

Анализ проблемы: неявный серверный вызов (Roundtrip)

Посмотрим на пример клиентского кода, который часто пишется для смены активности кнопок:


&НаКлиенте
Процедура МенюНажатиеПродажи(Команда)
    СброситьАктивностьКнопок();
    Элементы.КнопкаМенюПродажи.Картинка = БиблиотекаКартинок.Продажи48Активная;
    Элементы.ОсновнаяПанель.ТекущаяСтраница = Элементы.стрПродажи;
КонецПроцедуры

&НаКлиенте
Процедура СброситьАктивностьКнопок()
    Элементы.КнопкаМенюПродажи.Картинка = БиблиотекаКартинок.Продажи48;
    Элементы.КнопкаМенюДокументы.Картинка = БиблиотекаКартинок.Документы48;
КонецПроцедуры

Несмотря на то, что обработчик объявлен с директивой &НаКлиенте, а картинки берутся из объекта БиблиотекаКартинок, форма начинает зависать. Выясним причину такого поведения платформы:

  1. Особенности свойства Картинка объекта КнопкаФормы: В синтакс-помощнике для свойства Картинка указано: «Изменение свойства на клиенте требует обращения к серверу». Это структурное свойство метаописания интерфейса. Присвоение ему нового значения не кешируется локально, а инициирует неявный контекстный вызов сервера.
  2. Сброс и перерисовка состояния формы: При контекстном серверном вызове на сервер неявно передается вся форма. Платформа перестраивает описание интерфейса и возвращает его клиенту.
  3. Каскадное обновление динамических списков: Если на форме размещены «тяжелые» элементы (динамические списки, большие таблицы), то при возврате контекста формы платформа инициирует повторное считывание данных из базы для активных списков. При совмещении смены картинок с переключением ТекущаяСтраница открывающийся список тут же отправляет запросы к СУБД, что и создает видимый эффект зависания.

Проанализируем практические альтернативы, которые позволяют решить задачу без обращения к серверу.

Решение 1. Использование стандартных закладок группы «Страницы»

Самый простой и правильный с точки зрения архитектуры 1С способ — отказаться от отдельных кнопок и использовать штатные возможности элемента ГруппаФормы с видом Страницы:

  1. Установим у группы страниц свойство ОтображениеЗакладок в значение Картинки или КартинкиИЗаголовок.
  2. В свойствах каждой подчиненной страницы укажем соответствующую иконку из библиотеки картинок.
  3. Настроим расположение закладок (сверху, слева и т. д.).

Переключение между страницами в таком режиме выполняется встроенным клиентским движком платформы абсолютно без вызовов сервера и перерисовки всей формы.

Решение 2. Поле формы с видом «Поле переключателя»

Если требуется стилизовать меню под горизонтальный или вертикальный ряд кнопок, применим ПолеФормы с видом переключателя:

  1. Создадим реквизит формы ТекущийРазделМеню с типом Строка или Число.
  2. Разместим на форме поле, свяжем его с этим реквизитом и укажем ВидПереключателя = Кнопки или Тумблер.
  3. Заполним СписокВыбора значениями пунктов меню, прикрепив к каждому элементу свою картинку.
  4. В клиентском событии ПриИзменении переключателя будем управлять отображением страниц.

Посмотрим на пример клиентского обработчика:


&НаКлиенте
Процедура ТекущийРазделМенюПриИзменении(Элемент)
    Если ТекущийРазделМеню = "Продажи" Тогда
        Элементы.ОсновнаяПанель.ТекущаяСтраница = Элементы.стрПродажи;
    ИначеЕсли ТекущийРазделМеню = "Документы" Тогда
        Элементы.ОсновнаяПанель.ТекущаяСтраница = Элементы.стрДокументы;
    КонецЕсли;
КонецПроцедуры

Переключение тумблера и смена активной страницы в этом случае происходят полностью на стороне тонкого клиента.

Решение 3. Выделение активности через цвет оформления кнопки

Если необходимо сохранить именно элементы КнопкаФормы, то вместо изменения свойства Картинка следует управлять цветом оформления. В отличие от картинки, изменение свойств ЦветФона, ЦветТекста и ЦветРамки у кнопок выполняется на клиенте локально и не инициирует серверных вызовов.

Разберем пример реализации:


&НаКлиенте
Процедура МенюНажатиеПродажи(Команда)
    ВыделитьАктивнуюКнопку(Элементы.КнопкаМенюПродажи);
    Элементы.ОсновнаяПанель.ТекущаяСтраница = Элементы.стрПродажи;
КонецПроцедуры

&НаКлиенте
Процедура ВыделитьАктивнуюКнопку(АктивнаяКнопка)
    // Сбрасываем оформление кнопок меню
    Элементы.КнопкаМенюПродажи.ЦветФона = WebЦвета.Белый;
    Элементы.КнопкаМенюДокументы.ЦветФона = WebЦвета.Белый;
    
    // Устанавливаем цвет для выбранной кнопки
    АктивнаяКнопка.ЦветФона = WebЦвета.СветлоСерый;
КонецПроцедуры

Решение 4. Управление видимостью парных кнопок

Еще один вариант реализации — разместить в структуре формы для каждого пункта по две кнопки: одну в обычном состоянии, другую — в активном. Начиная с платформы 8.3.7, переключение свойства Видимость элементов формы на клиенте не вызывает неявного обращения к серверу.

Посмотрим, как организовать переключение видимости:


&НаКлиенте
Процедура АктивироватьКнопку(КнопкаОбычная, КнопкаАктивная)
    // Включаем видимость обычных кнопок и скрываем активные
    Элементы.КнопкаПродажи.Видимость = Истина;
    Элементы.КнопкаПродажиАктивная.Видимость = Ложь;
    Элементы.КнопкаДокументы.Видимость = Истина;
    Элементы.КнопкаДокументыАктивная.Видимость = Ложь;
    
    // Для выбранного пункта меняем видимость
    КнопкаОбычная.Видимость = Ложь;
    КнопкаАктивная.Видимость = Истина;
КонецПроцедуры

Оптимизация динамических списков при переключении страниц

Если на страницах панели расположены динамические списки, которые при переходе создают нагрузку, применим механизм отложенной загрузки (Lazy Loading):

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

Это исключит одновременное обращение ко всем источникам данных и обеспечит быстрый отклик интерфейса.

← На главную