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