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