Почему ЭлементФормы.ТолькоПросмотр не устанавливается в значение Ложь и как это исправить

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

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

Проблема программного цикла по элементам

Рассмотрим ситуацию, описанную в исходном коде. Программист обходит все элементы формы в цикле и устанавливает им режим «Только просмотр», а затем пытается точечно «открыть» один элемент. Проблема заключается в том, что в управляемых и обычных формах 1С свойство ТолькоПросмотр обладает иерархической зависимостью.

Проанализируем фрагмент кода:


Для каждого ЭлементФормы Из ЭтаФорма.Элементы цикл
    Попытка
        ЭлементФормы.ТолькоПросмотр = Результат; // Здесь устанавливается Истина
    Исключение
        // Игнорируем элементы, не имеющие этого свойства
    КонецПопытки;
КонецЦикла;

// Попытка сделать доступным один элемент
ЭтаФорма.Элементы.ПередатьВПроизводство.ТолькоПросмотр = Ложь; 

В данном случае, если элемент ПередатьВПроизводство находится внутри какой-либо группы (например, в «Группе основных реквизитов» или на странице панели), то в цикле вы установили ТолькоПросмотр = Истина не только для самого элемента, но и для его родительской группы. Согласно логике платформы, если родитель (группа) заблокирован для редактирования, его дочерние элементы не могут быть открыты для записи, какие бы значения им ни присваивались в коде. Это фундаментальное правило наследования интерфейсных свойств.

Разберем причины блокировки по шагам

Выясним, какие факторы могут мешать корректной установке свойства ТолькоПросмотр:

  1. Наследование от родителей. Это самая распространенная причина. Если элемент вложен в ГруппаФормы, и у этой группы установлено ТолькоПросмотр = Истина, дочерний элемент всегда будет доступен только для чтения.
  2. Свойство самой формы. Если вы установили ЭтаФорма.ТолькоПросмотр = Истина, платформа блокирует ввод данных для всей формы целиком. В этом режиме индивидуальные настройки элементов игнорируются.
  3. Условное оформление. В управляемом интерфейсе УсловноеОформление имеет высший приоритет при отрисовке. Если в настройках формы задано правило, блокирующее реквизит, программная установка свойства в процедуре ПриОткрытии может быть перекрыта платформой в момент финального вывода формы на экран.
  4. Состояние объекта данных. Если основной реквизит формы (документ) уже проведен или помечен на удаление, платформа автоматически переводит форму в режим чтения. Попытки «оживить» отдельные элементы могут блокироваться на уровне ядра.
  5. Права доступа (Роли). Если у пользователя нет прав на изменение данного поля или объекта в целом (ReadOnly на уровне метаданных), свойство ТолькоПросмотр будет принудительно равно Истина.

Как решить задачу правильно: Метод исключения

Вместо того чтобы сначала закрывать всё, а потом пытаться открыть один элемент, мы рекомендуем использовать «белый список» элементов. Рассмотрим, как переписать процедуру блокировки более грамотно, избегая воздействия на родительские группы.

Проанализируем правильный подход к написанию цикла:


Процедура ЗаблокироватьФормуСИсключениями(НужноБлокировать)
    
    // Определяем список имен элементов, которые ДОЛЖНЫ остаться доступными
    СписокИсключений = Новый СписокЗначений;
    СписокИсключений.Добавить("ПередатьВПроизводство");
    СписокИсключений.Добавить("ГруппаКнопокДействий"); // Если нужно оставить доступными кнопки внутри группы
    
    Для каждого Элемент Из ЭтаФорма.Элементы Цикл
        
        // Проверяем, не входит ли элемент в список исключений
        Если СписокИсключений.НайтиПоЗначению(Элемент.Имя) = Неопределено Тогда
            
            // Проверяем тип элемента, так как не все поддерживают ТолькоПросмотр
            // (например, Группы или Декорации)
            Если ТипЗнч(Элемент) = Тип("ПолеФормы") 
               Или ТипЗнч(Элемент) = Тип("ТаблицаФормы") Тогда
               
                Элемент.ТолькоПросмотр = НужноБлокировать;
                
            КонецЕсли;
            
        Иначе
            // Для исключений принудительно открываем доступ
            Элемент.ТолькоПросмотр = Ложь;
        КонецЕсли;
        
    КонецЦикла;

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

Важность проверки типа данных в условии

Обратим внимание на сообщение из темы форума, где упоминается проверка Если Результат Тогда. Если переменная Результат содержит число (например, количество часов), то в 1С число 0 воспринимается как Ложь, а любое другое число (в том числе отрицательное) — как Истина.

Посмотрим на пример правильного вычисления условия:


РазницаВЧасах = УправлениеЗаявкамиСервер.ПолучитьРазницуМеждуДатамиВЧасах(Объект.Дата, ТекущаяДата());

// Четко определяем булево значение
НужноБлокировать = (РазницаВЧасах >= 24);

Если НужноБлокировать Тогда
    // Вызываем нашу процедуру блокировки
    ЗаблокироватьФормуСИсключениями(Истина);
КонецЕсли;

Различие между ТолькоПросмотр и Доступность

Иногда разработчики путают свойства ТолькоПросмотр и Доступность. Разберем их отличия:

Если вы работаете с кнопками (командами), то у них часто нет свойства ТолькоПросмотр. В этом случае необходимо использовать Доступность. Если ваша цель — оставить чекбокс (флажок) рабочим, используйте именно ТолькоПросмотр = Ложь, но убедитесь, что все его «родители» в дереве элементов формы также имеют ТолькоПросмотр = Ложь.

Использование Условного оформления

Если ваша конфигурация реализована на Управляемых формах (УФ), наиболее современным и надежным способом является использование Условного оформления. Это позволяет избежать написания громоздких циклов в коде ПриОткрытии.

Посмотрим, как это настроить программно в процедуре ПриСозданииНаСервере:


ЭлементОформления = УсловноеОформление.Элементы.Добавить();

// Устанавливаем само свойство
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);

// Устанавливаем условие (например, если дата документа старая)
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Дата");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
ЭлементУсловия.ПравоеЗначение = ТекущаяДата() - 86400; // 24 часа в секундах

// Указываем, какие поля блокировать (кроме нашего исключения)
Для каждого Поле Из ЭтаФорма.Элементы Цикл
    Если Поле.Имя <> "ПередатьВПроизводство" И ТипЗнч(Поле) = Тип("ПолеФормы") Тогда
        ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
        ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных(Поле.Имя);
    КонецЕсли;
КонецЦикла;

Такой подход гарантирует, что даже при изменении данных на форме (например, при пересчете дат) платформа сама актуализирует доступность полей, не требуя повторного запуска тяжелых циклов обхода коллекции Элементы.

Резюме и рекомендации

Подводя итог, если вы столкнулись с тем, что ТолькоПросмотр не сбрасывается в Ложь, выполните следующие действия:

  1. Проверьте свойство ТолькоПросмотр у всех родительских групп, в которые входит элемент.
  2. Убедитесь, что сама форма (ЭтаФорма) не находится в режиме «Только просмотр».
  3. Проверьте права доступа текущего пользователя к реквизиту.
  4. Используйте отладчик, чтобы убедиться, что после вашего кода никакие другие процедуры (например, ПриЧтенииНаСервере) не переопределяют свойства элементов.
  5. При разработке на управляемых формах отдавайте предпочтение Условному оформлению вместо прямого перебора элементов в цикле.

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

← На главную