Как программно наложить отбор на уже открытую форму списка в 1С?

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

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

Использование ключа уникальности для поиска формы

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

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


ПараметрыОтбора = Новый Структура("Отбор", Новый Структура("Статус", Перечисления.СтатусыЗаказов.Согласован));
КлючУникальности = "УникальныйИдентификаторМоейФормыСписка";
ОткрытьФорму("Документ.ЗаказПокупателя.ФормаСписка", ПараметрыОтбора, , КлючУникальности);

Если форма с ключом "УникальныйИдентификаторМоейФормыСписка" уже открыта, она просто активизируется. Однако здесь кроется важный нюанс: если форма уже была открыта, стандартный обработчик ПриСозданииНаСервере не выполнится повторно. Следовательно, простым перебором параметров в этом методе задачу не решить.

Обработка события ПриОбновленииПараметров

Для того чтобы открытая форма "узнала", что ей передали новые параметры (в нашем случае — новый отбор), в современных версиях платформы (начиная с 8.3.3) используется обработчик события ПриОбновленииПараметров. Рассмотрим, как правильно реализовать логику внутри модуля формы списка:


&НаСервере
Процедура ПриОбновленииПараметров(НовыеПараметры)
    // Проверяем наличие структуры отбора в переданных параметрах
    Если НовыеПараметры.Свойство("Отбор") Тогда
        УстановитьОтборНаСервере(НовыеПараметры.Отбор);
    КонецЕсли;
КонецПроцедуры

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

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

Механизм оповещений: Оповестить и ОбработкаОповещения

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

Шаг 1. В вызывающей форме (например, из формы обработки) отправляем сигнал:


ПараметрыСобытия = Новый Структура;
ПараметрыСобытия.Вставить("ИмяПоля", "Контрагент");
ПараметрыСобытия.Вставить("Значение", ВыбранныйКонтрагент);
Оповестить("УстановитьФильтрСписка", ПараметрыСобытия);

Шаг 2. В форме списка, которая должна принять этот сигнал, создаем клиентский обработчик ОбработкаОповещения:


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

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

Фиксированные настройки против пользовательских

При программном изменении отборов крайне важно выбрать правильное место в КомпоновщикНастроек динамического списка. Выясним причину, почему это важно:

  1. КомпоновщикНастроек.Настройки.Отбор — это настройки, которые видит и может менять пользователь. Если вы программно добавите отбор сюда, пользователь сможет зайти в настройки списка и отключить его.
  2. КомпоновщикНастроек.ФиксированныеНастройки.Отбор — эти настройки накладываются платформой жестко. Они не видны пользователю в окне настроек и не могут быть им изменены. Это идеальное место для реализации логики, которая должна строго ограничивать данные (например, по правам доступа или конкретному бизнес-процессу).

Посмотрим на пример установки фиксированного отбора:


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

Прямой доступ через ПолучитьОкна()

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

Проанализируем алгоритм поиска:

  1. Вызываем ПолучитьОкна().
  2. Перебираем каждое окно и проверяем его содержимое (массив форм).
  3. Ищем форму по заголовку или по имени основного реквизита.
  4. Вызываем экспортный метод найденной формы.

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

Принудительное обновление списка

После того как мы изменили настройки КомпоновщикаНастроек, форма не всегда мгновенно обновляет данные на экране. Чтобы гарантировать актуальность отображаемой информации, рекомендуется явно вызвать метод обновления элемента формы:


&НаКлиенте
Элементы.Список.Обновить();

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

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

← На главную