Почему не закрывается форма выбора в 1С при программном открытии и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 на управляемых формах разработчики часто сталкиваются с ситуацией: в событии НачалоВыбора поля ввода открывается форма выбора справочника с наложенным отбором, однако после двойного клика по нужной строке окно выбора не закрывается, значение не переносится в поле ввода, а при повторном нажатии на кнопку выбора открываются новые дублирующие окна. Разберем детально, почему это происходит и как правильно организовать программный выбор данных.

Причины, почему форма выбора не закрывается и дублируется

Проанализируем базовый механизм работы управляемых форм 1С при выборе значений:

  1. Отсутствие владельца формы: если при вызове методов ОткрытьФорму или ПолучитьФорму не передан параметр Владелец (в качестве которого должен выступать элемент формы Элемент), форма выбора открывается автономно. Платформа не связывает окно выбора с конкретным полем ввода, поэтому при выборе элемента не инициируется передача значения и автоматическое закрытие окна, даже если свойство ЗакрыватьПриВыборе установлено в значение Истина.
  2. Некорректная работа с параметром уникальности: передача значения Истина в четвертый параметр метода ПолучитьФорму или ОткрытьФорму сообщает платформе о необходимости создавать каждый раз новый экземпляр формы. Если владелец не задан, повторные клики по кнопке выбора создают цепочку независимых незакрытых окон.
  3. Конфликт со стандартной обработкой: если в процедуре НачалоВыбора не отключить стандартный механизм (СтандартнаяОбработка = Ложь), платформа продолжит выполнять штатное действие параллельно с открытием вашей формы, что приводит к непредсказуемому поведению интерфейса (например, открытию формы редактирования элемента).

Способ 1. Корректное программное открытие через ОткрытьФорму с передачей владельца

Рассмотрим правильный вариант реализации обработчика НачалоВыбора. В управляемом приложении не рекомендуется использовать устаревшую связку ПолучитьФорму + ОткрытьФорму. Вместо этого вызываем единую процедуру ОткрытьФорму, куда передаем имя формы выбора, структуру параметров и обязательно указываем поле ввода в качестве владельца формы.

Посмотрим на пример правильного кода:


&НаКлиенте
Процедура НомерЦехаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // 1. Отключаем штатное открытие формы платформой
    СтандартнаяОбработка = Ложь;
    
    // 2. Формируем параметры открытия
    ПараметрыФормы = Новый Структура;
    
    Отбор = Новый Структура;
    Отбор.Вставить("Свойство", ПолучитьЦех());
    ПараметрыФормы.Вставить("Отбор", Отбор);
    
    // Явно указываем режим выбора и закрытие формы
    ПараметрыФормы.Вставить("РежимВыбора", Истина);
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
    
    // 3. Открываем форму, передавая Элемент в качестве владельца
    ОткрытьФорму("Справочник.ЗначенияСвойствОбъектов.ФормаВыбора", ПараметрыФормы, Элемент);

КонецПроцедуры

Разберем по шагам, что изменилось:

  1. Мы установили СтандартнаяОбработка = Ложь, предотвратив двойной запуск выбора.
  2. В третьем параметре функции ОткрытьФорму мы передали Элемент (элемент управления поля ввода). Теперь форма выбора знает, куда вернуть результат.
  3. При выборе элемента форма автоматически закроется, а в вызывающей форме сработает стандартное событие ОбработкаВыбора для данного элемента.

Способ 2. Использование оповещения о выборе (через ОписаниеОповещения)

Если требуется нестандартная логика обработки выбранного значения (например, заполнить сразу несколько реквизитов документа или выполнить дополнительную валидацию), рассмотрим способ с явным описанием процедуры обратного вызова.

Посмотрим на пример:


&НаКлиенте
Процедура НомерЦехаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("Свойство", ПолучитьЦех()));
    ПараметрыФормы.Вставить("РежимВыбора", Истина);
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
    
    ОповещениеОВыборе = Новый ОписаниеОповещения("ПослеВыбораЦеха", ЭтотОбъект);
    
    // Передаем форму документа в качестве владельца и оповещение о закрытии
    ОткрытьФорму("Справочник.ЗначенияСвойствОбъектов.ФормаВыбора", ПараметрыФормы, ЭтотОбъект,,,, ОповещениеОВыборе);

КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЦеха(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    Если ЗначениеЗаполнено(РезультатВыбора) Тогда
        Объект.НомерЦеха = РезультатВыбора;
    КонецЕсли;

КонецПроцедуры

В самой форме выбора (если она кастомная) для завершения подбора используется платформенная процедура ОповеститьОВыборе(ВыбранноеЗначение), которая возвращает значение в процедуру ПослеВыбораЦеха и гарантированно закрывает окно выбора.

Способ 3. Настройка отбора без написания кода в НачалоВыбора

Выясним причину, почему разработчики часто переопределяют событие НачалоВыбора. Чаще всего это делается исключительно ради наложения простого отбора. Однако в платформе 1С 8.3 для этого предусмотрены штатные декларативные механизмы, которые работают надежнее и не требуют открытия форм вручную:

  1. Свойство «Связи параметров выбора»: если отбор зависит от другого реквизита текущего документа (например, от реквизита Свойство), связь настраивается в свойствах реквизита в дереве метаданных без единой строчки кода на клиенте.
  2. Свойство «Параметры выбора»: если отбор фиксированный, его можно задать в конфигураторе или программно при создании формы на сервере:
    
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        
        МассивПараметров = Новый Массив;
        МассивПараметров.Добавить(Новый ПараметрВыбора("Отбор.Свойство", ПолучитьЦех()));
        
        Элементы.НомерЦеха.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
    
    КонецПроцедуры
    

При использовании ПараметрыВыбора форма выбора открывается штатно: платформа сама передает владельца, корректно обрабатывает выбор значения и закрывает окно выбора.

Итоги и рекомендации

Для того чтобы форма выбора закрывалась автоматически и не создавала дубликатов окон:

  1. Всегда устанавливайте СтандартнаяОбработка = Ложь в обработчике НачалоВыбора, если открываете форму вручную.
  2. Всегда передавайте Элемент (или ЭтотОбъект) в параметр Владелец метода ОткрытьФорму.
  3. Используйте метод ОткрытьФорму вместо устаревшего ПолучитьФорму.
  4. Для простых отборов отдавайте предпочтение свойству ПараметрыВыбора или механизму СвязиПараметровВыбора.
← На главную