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