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