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