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