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