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