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