В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача: открыть форму с определенным набором параметров, но при этом избежать дублирования окон. Если форма с такими параметрами уже открыта, она должна быть активизирована, а не создана заново. Однако, когда в качестве ключа уникальности используется объект типа Структура, стандартный механизм 1С начинает вести себя не совсем так, как ожидает разработчик. Разберем эту ситуацию подробно и найдем оптимальные пути решения.
Рассмотрим стандартный вызов открытия формы. Программист создает структуру параметров, помещает в нее данные и передает ее в метод ОткрытьФорму, указывая эту же структуру (или ее часть) в качестве параметра Уникальность. Проблема заключается в том, что в языке 1С коллекции (такие как Структура, Массив, СписокЗначений) являются ссылочными типами данных. Когда вы пишете Новый Структура, вы создаете новый объект в памяти с уникальным адресом.
Платформа при проверке уникальности сравнивает не внутреннее содержимое структур, а именно их ссылки в памяти. Даже если две структуры содержат абсолютно идентичные ключи и значения, для платформы они будут разными объектами. В результате, при каждом нажатии на кнопку будет открываться новое окно, что перегружает интерфейс и путает пользователя.
Выясним основной принцип: для надежной работы механизма уникальности в качестве ключа следует использовать примитивные типы данных: Строка, Число или УникальныйИдентификатор. Самый простой способ превратить структуру в уникальную строку — использовать сериализацию.
Проанализируем ситуацию, когда код выполняется на стороне сервера. Мы можем использовать метод ЗначениеВСтрокуВнутр. Этот метод создает строковое представление объекта, которое будет идентичным для одинакового содержимого (при условии одинакового порядка свойств).
// На сервере или в толстом клиенте
ПараметрыФормы = Новый Структура("КлючСвязи", ТекущийОбъект);
КлючУникальности = ЗначениеВСтрокуВнутр(ПараметрыФормы);
ОткрытьФорму("Справочник.Номенклатура.ФормаОбъекта", ПараметрыФормы, , КлючУникальности);
Однако стоит помнить, что порядок свойств в Структуре не гарантирован. Чтобы избежать ситуации, когда одинаковые наборы данных дают разные строки, рекомендуется использовать СписокЗначений, предварительно отсортировав его по ключам, или вручную собирать строку из значений полей.
Если открытие формы происходит полностью на стороне тонкого клиента, метод ЗначениеВСтрокуВнутр нам недоступен. В современных версиях платформы (8.3.6 и выше) для этих целей идеально подходит работа с JSON. Это позволяет сформировать уникальный ключ без лишнего контекстного вызова сервера.
Посмотрим на пример формирования ключа через JSON:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураПараметров);
СтрокаКлюч = ЗаписьJSON.Закрыть();
ОткрытьФорму("ОбщаяФорма.МояФорма", ПараметрыФормы, , СтрокаКлюч);
Важный нюанс: если ваша структура содержит 50 и более полей, результирующая строка может стать слишком длинной. В таких случаях целесообразно использовать хеширование (например, MD5), чтобы получить строку фиксированной длины, которая будет однозначно идентифицировать ваш набор параметров.
Многие разработчики сталкиваются с тем, что при активации уже открытой формы данные в ней не обновляются. Это происходит потому, что обработчик ПриСозданииНаСервере и событие ПриОткрытии срабатывают только один раз — при физическом создании окна. Если платформа нашла существующее окно по ключу уникальности, она просто выводит его на передний план.
Чтобы обновить данные в форме, необходимо обязательно использовать обработчик ПриПовторномОткрытии(Параметры) в модуле формы. Проанализируем, как это работает: в этот обработчик передается структура параметров, которую вы отправили в метод ОткрытьФорму. Здесь вы должны программно обновить реквизиты формы.
&НаКлиенте
Процедура ПриПовторномОткрытии(Параметры)
// Проверяем, изменились ли данные
Если Параметры.Свойство("НекаяСтруктура") Тогда
// Вызываем серверный метод для обновления данных формы
ОбновитьДанныеНаФормеСервер(Параметры.НекаяСтруктура);
КонецЕсли;
КонецПроцедуры
В некоторых сложных случаях стандартный параметр Уникальность может быть недостаточно гибким. Например, если логика сравнения параметров подразумевает игнорирование некоторых полей. Тогда мы можем пойти по пути ручного управления окнами.
Разберем алгоритм поиска:
ПолучитьОкна() для получения списка всех открытых окон приложения.Содержимое[0] является нужной нам формой, проверяем её параметры.Активизировать().Этот способ более трудоемкий, но он дает 100% контроль над процессом поиска дублей, позволяя реализовывать самую причудливую логику сравнения данных.
Для корректной работы уникальности управляемой формы помните следующие правила:
Структура в параметр Уникальность, если хотите найти существующее окно по содержимому этой структуры.ПриПовторномОткрытии для обновления данных, иначе пользователь увидит "старое" состояние формы.Уникальность с КлючНазначенияИспользования. Второй отвечает только за сохранение пользовательских настроек (размеры окна, видимость колонок), а не за предотвращение открытия дублей.Соблюдение этих принципов позволит вам создавать отзывчивый и интуитивно понятный интерфейс, где каждое окно находится на своем месте и содержит актуальную информацию.