Как подменить форму выбора элемента, сохранив связи параметров выбора?

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

В практике разработки на платформе 1С:Предприятие часто возникает задача: необходимо открыть нестандартную форму выбора для конкретного поля ввода (например, форму с особым дизайном или алгоритмом), но при этом нельзя потерять настроенные в конфигураторе «Связи параметров выбора». Если мы просто отключаем стандартную обработку, платформа перестает накладывать фильтры автоматически. Давайте разберем подробно, как решить эту проблему, сохранив логику работы системы.

Суть проблемы и стандартное поведение

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

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

СтандартнаяОбработка = Ложь;

Мы сообщаем платформе: «Я сам все сделаю». В этот момент автоматическое наложение отборов по связям отключается. Если просто открыть свою форму методом ОткрытьФорму, пользователь увидит полный список элементов без фильтрации. Наша задача — восстановить эту фильтрацию или использовать механизм переопределения формы.

Способ 1. Локальная подмена через передачу параметров (Рекомендуемый)

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

Логика действий следующая:

  1. В процедуре НачалоВыбора отключаем стандартную обработку.
  2. Формируем структуру отбора, дублирующую логику связей.
  3. Передаем эту структуру в параметры открываемой формы.

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


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

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

&НаКлиенте
Процедура ОбработкаВыбораЭлемента(Результат, ДополнительныеПараметры) Экспорт
    
    // Если пользователь ничего не выбрал (закрыл окно), Результат будет Неопределено
    Если Результат <> Неопределено Тогда
        // ДополнительныеПараметры в данном случае содержат ссылку на Элемент формы
        ЭлементФормы = ДополнительныеПараметры;
        
        // Присваиваем выбранное значение реквизиту, связанному с элементом
        // Внимание: ЭлементФормы.ПутьКДанным содержит строку с именем реквизита
        // Но проще присвоить через контекст данных, если вы знаете имя реквизита,
        // или использовать прямое присваивание, если это поддерживается типом элемента.
        
        // Самый простой вариант для управляемых форм, если передан Элемент как владелец:
        // Платформа часто сама подставляет значение при выборе, если владелец указан верно.
        // Но если нет - прописываем явно:
        Объект[ЭлементФормы.Имя] = Результат;
    КонецЕсли;

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

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

Способ 2. Глобальная подмена через Модуль менеджера

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

Для этого используется обработчик ОбработкаПолученияФормы в модуле менеджера справочника.

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


// Модуль менеджера справочника (на Сервере)

Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
    
    // Проверяем условие, при котором нужна подмена.
    // Например, если это мобильный клиент или определенная роль пользователя.
    // В данном примере проверим просто ВидФормы, но в реальности условий может быть больше.
    
    Если ВидФормы = "ФормаВыбора" Тогда
        
        // Указываем путь к нашей специальной форме
        ВыбраннаяФорма = Метаданные.Справочники.МойСправочник.Формы.МояСпециальнаяФормаВыбора;
        
        // Устанавливаем СтандартнаяОбработка = Ложь, чтобы платформа приняла нашу форму
        СтандартнаяОбработка = Ложь;
        
        // ПЛЮС ЭТОГО МЕТОДА:
        // Все параметры (включая связи выбора и отборы), которые система собрала автоматически
        // в месте вызова, УЖЕ находятся в коллекции "Параметры".
        // Нам не нужно формировать их вручную, они просто передадутся в новую форму.
        
    КонецЕсли;

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

Преимущества метода:

Недостатки метода:

Анализ: какой метод выбрать?

Давайте проанализируем ситуацию автора вопроса. У него есть "элемент программно добавленный на форму". Это означает, что это частный случай интерфейса.

В этом случае Способ 2 (Модуль менеджера) применять опасно и архитектурно неверно, так как изменение затронет весь справочник. Правильным решением будет Способ 1 (Локальная подмена).

Если вы хотите сделать код универсальным и не перечислять параметры вручную ("Вася", "Лошпед"), можно программно прочитать связи элемента. У объекта Элемент (тип ПолеФормы) есть коллекция СвязиПараметровВыбора.

Вы можете написать универсальную функцию, которая:

  1. Перебирает коллекцию Элемент.СвязиПараметровВыбора.
  2. Находит значения соответствующих реквизитов в Объект.
  3. Собирает из них структуру для параметра Отбор.
  4. Открывает форму.

Но в большинстве случаев, когда вы точно знаете логику работы вашей формы, проще и нагляднее явно прописать структуру отбора, как показано в примере Способа 1.

← На главную