Почему не срабатывает ОписаниеОповещения при вызове ОткрытьФорму и как это исправить?

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

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

Разбор стандартного механизма вызова с оповещением

Рассмотрим типовую ситуацию. Предположим, нам необходимо реализовать выбор объекта в зависимости от типа, который определяется динамически. Программист пишет процедуру в модуле формы, используя асинхронный подход, обязательный для современных конфигураций и веб-клиента. Проанализируем исходный код, который часто приводит к ошибке:


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

&НаКлиенте
Процедура ВыборОбъектаДокументаЗавершение(ЗначениеВыбора, Параметры) Экспорт
    Если ЗначениеВыбора <> Неопределено Тогда
        Сообщить("Выбор успешно завершен: " + ЗначениеВыбора);
    КонецЕсли;
КонецПроцедуры

В приведенном примере на первый взгляд все верно: создано ОписаниеОповещения, указана экспортная процедура, форма открывается модально по отношению к владельцу. Однако на практике процедура ВыборОбъектаДокументаЗавершение может никогда не вызваться. Почему так происходит? Выясним причину, скрытую в механизмах платформы.

Влияние события ОбработкаПолученияФормы

Одной из ключевых причин, почему «теряется» оповещение, является работа обработчика ОбработкаПолученияФормы в модуле менеджера объекта (например, справочника или документа). Когда мы вызываем форму по короткому пути вида Справочник.Сотрудники.ФормаВыбора, платформа инициирует цепочку событий:

  1. Система обращается к менеджеру объекта.
  2. Вызывается событие ОбработкаПолученияФормы.
  3. В этом событии разработчик конфигурации может переопределить, какая именно форма должна открыться, или изменить параметры её создания.

Если в этом системном событии происходит подмена формы или некорректная передача параметров, связь с объектом ОписаниеОповещения может разорваться. Платформа «забывает», что вызывающая сторона ожидает ответа. Именно поэтому использование стандартных имен форм часто приводит к нестабильной работе асинхронных вызовов.

Решение проблемы: Прямое обращение к метаданным

Как показала практика и обсуждения опытных разработчиков, существует эффективный обходной путь. Вместо использования «короткого» пути к форме, следует использовать «полный» путь, включающий ключевое слово Форма (или Form).

Сравним два варианта обращения:

Рассмотрим исправленный код, который гарантирует срабатывание оповещения:


// Вместо конструкции:
// ФФФ = ОткрытьФорму(ЭтаФорма.ТипОбъекта + ".ФормаВыбора", ...);

// Используем прямое обращение:
ПутьКФорме = ЭтаФорма.ТипОбъекта + ".Форма.ФормаВыбора";
ОткрытьФорму(ПутьКФорме, , , , , , Опаньки, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

Проанализируем ситуацию: почему это работает? При указании полного пути .Форма.ИмяФормы платформа обращается напрямую к конкретному объекту метаданных, игнорируя событие менеджера ОбработкаПолученияФормы. Это позволяет избежать любых посредников и гарантирует, что ОписаниеОповещения будет «привязано» именно к тому окну, которое откроется на экране.

Альтернативный подход: Использование Владельца и события ОбработкаВыбора

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

В процедуре начала выбора мы передаем сам элемент управления (поле ввода) в качестве владельца:


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

В этом случае нам не нужно ОписаниеОповещения. Когда пользователь выберет значение в открывшейся форме, оно автоматически вернется в вызывающую форму. Для обработки этого значения (если нужна дополнительная логика) мы используем стандартное событие формы ОбработкаВыбора:


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    // Данное событие сработает автоматически после выбора значения в форме-владельце
    Если ТипЗнч(ИсточникВыбора) = Тип("УправляемаяФорма") И Найти(ИсточникВыбора.ИмяФормы, "ФормаВыбора") > 0 Тогда
        Сообщить("Мы получили значение: " + ВыбранноеЗначение);
    КонецЕсли;
КонецПроцедуры

Важные технические нюансы

При работе с ОписаниеОповещения крайне важно соблюдать следующие правила, без которых механизм не будет работать вне зависимости от пути к форме:

1. Обязательный признак Экспорт

Процедура, указанная в ОписаниеОповещения, должна быть обязательно помечена ключевым словом Экспорт. Если процедура находится в модуле той же формы, она всё равно должна быть экспортной, так как вызов происходит из контекста другой формы (формы выбора).

2. Корректное закрытие формы выбора

Оповещение срабатывает только в момент закрытия вызванной формы. При этом форма должна закрываться методом Закрыть(), в который передается выбранное значение. Если в форме выбора используется стандартная кнопка «Выбрать», платформа делает это автоматически. Если же форма закрывается «крестиком» или по клавише Esc, в оповещение придет значение Неопределено.

3. Параметр Уникальность

При использовании ОткрытьФорму обратите внимание на параметр Уникальность. Если форма с таким ключом уже открыта, система не создаст новое окно, а активирует старое. В некоторых случаях это может привести к тому, что новое оповещение не будет зарегистрировано для уже существующего окна.

Резюме по решению проблемы

Если вы столкнулись с тем, что ОписаниеОповещения не отрабатывает при выборе объекта, рекомендуем выполнить следующие шаги для диагностики и исправления:

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

Использование полного пути к форме метаданных — это наиболее универсальный и надежный способ в тех случаях, когда требуется динамическое построение имени формы и гарантированный возврат результата через ОписаниеОповещения. Это позволяет избежать конфликтов с логикой конфигурации и обеспечивает стабильную работу кода в любых режимах запуска.

← На главную