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