Разработчики на платформе 1С часто сталкиваются с неприятным поведением управляемых форм: при программном изменении свойства Видимость (Visibility) любого элемента (кнопки, группы или поля) динамический список, находящийся на этой же форме, внезапно инициирует обновление данных. Это приводит к лишним серверным вызовам, «прыжкам» фокуса и замедлению работы интерфейса. В данной статье мы подробно разберем, почему так происходит и какие существуют методы обхода этой архитектурной особенности платформы.
Для начала проанализируем ситуацию с точки зрения механизмов платформы 1С. В управляемом приложении изменение свойства Видимость (Visibility) — это не просто скрытие элемента с экрана. Платформа интерпретирует это как изменение структуры формы. Это влечет за собой полную перекомпоновку (Layout) всей формы на стороне сервера.
Рассмотрим подробнее механику процесса:
Элементы.ИмяКнопки.Видимость = Ложь.Выяснив причину, разберем по шагам наиболее эффективные способы решения этой проблемы.
Это самый простой и рекомендуемый способ. В отличие от Видимости, изменение свойства Доступность (Enabled) не приводит к перестроению Layout всей формы. Элемент остается на своем месте, его размеры не меняются, он просто становится серым (неактивным).
Рассмотрим, как это реализовать:
Вместо скрытия кнопки в контекстном меню или на командной панели, мы просто отключаем возможность ее нажатия. Проанализируем пример кода:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Вместо Элементы.КомандаУдалить.Видимость = Ложь
Элементы.КомандаУдалить.Доступность = (ТекущиеДанные.Статус <> ПредопределенноеЗначение("Перечисление.Статусы.Заблокирован"));
КонецЕсли;
КонецПроцедуры
При таком подходе динамический список не будет перезапрашивать данные, так как структура формы остается стабильной. Пользователь видит кнопку, но не может ее нажать, что является стандартным паттерном для многих интерфейсов.
Если по требованиям дизайна кнопки должны оставаться визуально активными, но срабатывать только в определенных условиях, мы можем оставить их видимыми всегда. А логику «скрытия» перенести внутрь самой команды.
Посмотрим на пример реализации:
Видимой и Доступной постоянно.
&НаКлиенте
Процедура ВыполнитьДействие(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Если Не МожноВыполнятьОперацию(ТекущиеДанные) Тогда
ПоказатьПредупреждение(, "Для данной строки это действие недоступно!");
Возврат;
КонецЕсли;
// Основная логика команды
КонецПроцедуры
Этот метод полностью исключает влияние интерфейсных манипуляций на поведение динамического списка.
Иногда требуется именно скрывать элементы, и делать это нужно при перемещении по строкам списка (в событии ПриАктивизацииСтроки). Прямое изменение видимости в этом событии гарантированно вызывает «фризы» из-за циклического обновления. Мы можем применить хитрость с ПодключитьОбработчикОжидания.
Разберем по шагам, как это работает:
Мы отделяем событие активации строки от процесса изменения интерфейса. Программа фиксирует выбор строки, завершает стандартные процедуры платформы, и только через доли секунды меняет видимость.
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
// Откладываем обновление интерфейса на 0.1 - 0.2 секунды
ПодключитьОбработчикОжидания("ОбновитьВидимостьКоманд", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьВидимостьКоманд()
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
НоваяВидимость = (ТекущиеДанные.Сумма > 1000);
Если Элементы.СпецДействие.Видимость <> НоваяВидимость Тогда
Элементы.СпецДействие.Видимость = НоваяВидимость;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный момент: обязательно проверяйте текущее состояние видимости перед установкой нового значения (Если Элементы.СпецДействие.Видимость <> НоваяВидимость). Если свойство уже установлено в нужное значение, повторная установка все равно может спровоцировать пересчет Layout.
Существует продвинутый технический прием, позволяющий «обмануть» механизм Layout. Вместо управления свойством Видимость конкретной кнопки, мы можем создать на форме специальную группу, у которой Видимость изначально установлена в Ложь (на уровне конфигуратора или ПриСозданииНаСервере).
Проанализируем алгоритм:
СкрытоеХранилище (Видимость = Ложь).Элементы.Переместить().Этот метод считается более «тяжелым» программно, но в ряде случаев он позволяет избежать принудительного обновления данных в ДинамическомСписке, так как корневая структура видимых элементов меняется менее радикально.
Если задача стоит в том, чтобы дать пользователю понять, что команда изменилась, попробуйте менять заголовок (Caption) или картинку (Picture) вместо скрытия кнопки целиком. Изменение текста или иконки кнопки не меняет размеры элемента в большинстве случаев и не вызывает перестроения всей формы.
Пример кода:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные.Проведен Тогда
Элементы.КнопкаДействия.Заголовок = "Отменить проведение";
Элементы.КнопкаДействия.Картинка = БиблиотекаКартинок.ОтменаПроведения;
Иначе
Элементы.КнопкаДействия.Заголовок = "Провести";
Элементы.КнопкаДействия.Картинка = БиблиотекаКартинок.Провести;
КонецЕсли;
КонецПроцедуры
Мы выяснили, что основной причиной проблемы является механизм Layout управляемой формы. Чтобы ваша форма работала быстро, а динамический список не «прыгал», придерживайтесь следующих правил:
Доступность (Enabled).ПодключитьОбработчикОжидания для изоляции тяжелых операций обновления интерфейса от событий навигации по списку.Видимость (Visibility) в коде, который выполняется часто (например, при каждом движении курсора).Применяя эти подходы, вы обеспечите плавную и стабильную работу интерфейса вашего решения на базе 1С:Предприятие 8.3.