Как в 1С заблокировать форму для редактирования, оставив доступным только один элемент?

Программист 1С v8.3 (Управляемые формы)
← На главную

Рассмотрим частую задачу для разработчика 1С: необходимо сделать форму документа доступной только для просмотра при выполнении определенных условий (например, документ проведен и установлен некий флаг). Однако при этом один или несколько элементов, например, тот самый флаг, должны оставаться доступными для редактирования. Простая установка свойства ЭтаФорма.ТолькоПросмотр = Истина блокирует абсолютно все, и сделать исключение не получается. Разберемся, как правильно решить эту задачу.

Анализ неверных подходов и причина ошибки

Давайте проанализируем, почему стандартные подходы, которые первыми приходят в голову, не работают. Это поможет понять логику платформы и избежать ошибок в будущем.

Вариант 1: Блокировка всей формы с последующей разблокировкой элемента

Первая интуитивная попытка — установить режим "только просмотр" для всей формы, а затем для нужного элемента отменить это свойство.


// Этот код НЕ РАБОТАЕТ как ожидается
Если Объект.Ссылка.Проведен И Объект.ОтправкаВЗаявку = Истина Тогда
    ТолькоПросмотр = Истина; // Свойство формы
    // Попытка сделать галочку редактируемой
    ЭтаФорма.Элементы.ОтправкаВЗаявку.ТолькоПросмотр = Ложь; 
КонецЕсли;

Почему это не работает? Свойство формы ТолькоПросмотр является глобальным. Когда вы устанавливаете ЭтаФорма.ТолькоПросмотр = Истина, платформа принудительно устанавливает это свойство для всех элементов, связанных с данными, и блокирует стандартные команды, изменяющие данные ("Записать", "Провести"). Любые последующие попытки установить ТолькоПросмотр = Ложь для отдельных элементов будут проигнорированы. Это главное правило: свойство формы имеет приоритет над свойствами ее элементов.

Вариант 2: Перебор всех элементов в цикле

Второй логичный шаг — раз уж нельзя заблокировать все сразу, попробуем заблокировать все по отдельности, кроме нужного элемента.


// Этот код тоже может не сработать
Если Объект.ОтправкаВЗаявку = Истина и Объект.Проведен = Истина Тогда        
    Для Каждого Элемент Из ЭтаФорма.Элементы цикл 
        Если Элемент.Имя = "ОтправкаВЗаявку" Тогда
            Продолжить; // Пропускаем нашу галочку
        КонецЕсли;
        Элемент.ТолькоПросмотр = Истина;
    КонецЦикла;
КонецЕсли;

Почему это может не работать? Проблема кроется в иерархии элементов формы. Элементы часто располагаются внутри групп. Если в цикле свойство ТолькоПросмотр будет установлено для группы, то оно автоматически распространится на все вложенные в нее элементы. Таким образом, если ваша галочка "ОтправкаВЗаявку" находится внутри группы, которую ваш цикл заблокировал ранее, она тоже станет недоступной для редактирования, несмотря на явное исключение в коде.

Правильное решение: работа с группами элементов

Самый надежный, простой и поддерживаемый способ — это управление видимостью через правильную структуру элементов на форме. Суть метода в том, чтобы блокировать не отдельные элементы, а родительские группы, в которых они находятся.

Разберем по шагам, как это реализовать:

  1. Организуйте структуру формы. В редакторе формы в конфигураторе поместите элемент, который должен оставаться редактируемым (в нашем случае флажок `ОтправкаВЗаявку`), в отдельную, независимую группу. Например, `ГруппаУправленияОтправкой`.
  2. Сгруппируйте остальные элементы. Все остальные поля, таблицы и декорации, которые нужно заблокировать, поместите в одну или несколько крупных родительских групп. Например, `ГруппаШапка`, `ГруппаОсновное`, `ГруппаТабличныеЧасти`.
  3. Напишите код управления доступностью. В серверной процедуре (например, в событии ПриСозданииНаСервере или ПриЧтенииНаСервере) напишите код, который будет устанавливать свойство ТолькоПросмотр для этих крупных родительских групп.

Посмотрим на пример кода:

Предположим, на форме есть две основные группы ГруппаШапка и ГруппаТовары, а наша галочка находится в ГруппаУправленияОтправкой.


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    УстановитьДоступностьФормы();
КонецПроцедуры

&НаСервере
Процедура УстановитьДоступностьФормы()

    // Устанавливаем флаг блокировки по условию
    ЛокальнаяПеременнаяБлокировки = (Объект.Проведен И Объект.ОтправкаВЗаявку);

    // Устанавливаем свойство "ТолькоПросмотр" для родительских групп
    Элементы.ГруппаШапка.ТолькоПросмотр = ЛокальнаяПеременнаяБлокировки;
    Элементы.ГруппаТовары.ТолькоПросмотр = ЛокальнаяПеременнаяБлокировки;

    // Группу ГруппаУправленияОтправкой мы не трогаем, поэтому она и ее содержимое
    // остаются доступными для редактирования.

КонецПроцедуры

Этот подход элегантен и эффективен. Вам не нужно перебирать десятки элементов. Достаточно управлять свойством всего нескольких родительских групп. Платформа сама позаботится о том, чтобы свойство ТолькоПросмотр унаследовалось всеми дочерними элементами. Если в будущем вы добавите новые поля в `ГруппаШапка`, они автоматически будут блокироваться по заданной логике без изменения кода.

Важные нюансы и рекомендации

При работе с доступностью элементов стоит помнить о нескольких деталях, которые сделают ваше решение более надежным.

Доступность и ТолькоПросмотр

Это два разных свойства.

Для нашей задачи подходит именно ТолькоПросмотр.

Динамическое изменение доступности

Что если нужно, чтобы форма блокировалась сразу после установки галочки `ОтправкаВЗаявку` пользователем? В этом случае необходимо вызывать процедуру установки доступности из обработчика события ПриИзменении для этого флага.


&НаКлиенте
Процедура ОтправкаВЗаявкуПриИзменении(Элемент)
    // Вызываем серверную процедуру для пересчета доступности
    УстановитьДоступностьФормы(); 
КонецПроцедуры

В этом случае процедуру УстановитьДоступностьФормы() нужно будет объявить как серверную без контекста (&НаСервереБезКонтекста) или с контекстом, в зависимости от того, нужны ли ей данные формы, которые еще не записаны в объект.

Кнопки и команды

Для кнопок, которые выполняют код, изменяющий данные объекта, обязательно устанавливайте свойство "Изменяет данные" в палитре свойств. Если это свойство установлено в `Истина`, то кнопка автоматически станет неактивной, когда ее родительская группа или вся форма перейдет в режим `ТолькоПросмотр`. Это предотвратит случайное изменение данных через команды, когда поля ввода заблокированы.

В итоге, правильная организация структуры элементов на форме — ключ к простому и надежному управлению их доступностью. Вместо сложных циклов и проверок, используйте наследование свойств от родительских групп, и ваш код станет чище, а поведение формы — предсказуемее.

← На главную