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