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