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