Как обеспечить уникальность управляемой формы при использовании структуры в качестве ключа?

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

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

В чем заключается проблема уникальности?

Рассмотрим стандартный вызов открытия формы. Программист создает структуру параметров, помещает в нее данные и передает ее в метод ОткрытьФорму, указывая эту же структуру (или ее часть) в качестве параметра Уникальность. Проблема заключается в том, что в языке 1С коллекции (такие как Структура, Массив, СписокЗначений) являются ссылочными типами данных. Когда вы пишете Новый Структура, вы создаете новый объект в памяти с уникальным адресом.

Платформа при проверке уникальности сравнивает не внутреннее содержимое структур, а именно их ссылки в памяти. Даже если две структуры содержат абсолютно идентичные ключи и значения, для платформы они будут разными объектами. В результате, при каждом нажатии на кнопку будет открываться новое окно, что перегружает интерфейс и путает пользователя.

Решение 1: Преобразование структуры в строку (Ключ уникальности)

Выясним основной принцип: для надежной работы механизма уникальности в качестве ключа следует использовать примитивные типы данных: Строка, Число или УникальныйИдентификатор. Самый простой способ превратить структуру в уникальную строку — использовать сериализацию.

Проанализируем ситуацию, когда код выполняется на стороне сервера. Мы можем использовать метод ЗначениеВСтрокуВнутр. Этот метод создает строковое представление объекта, которое будет идентичным для одинакового содержимого (при условии одинакового порядка свойств).


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

Однако стоит помнить, что порядок свойств в Структуре не гарантирован. Чтобы избежать ситуации, когда одинаковые наборы данных дают разные строки, рекомендуется использовать СписокЗначений, предварительно отсортировав его по ключам, или вручную собирать строку из значений полей.

Решение 2: Использование JSON для клиентских вызовов

Если открытие формы происходит полностью на стороне тонкого клиента, метод ЗначениеВСтрокуВнутр нам недоступен. В современных версиях платформы (8.3.6 и выше) для этих целей идеально подходит работа с JSON. Это позволяет сформировать уникальный ключ без лишнего контекстного вызова сервера.

Посмотрим на пример формирования ключа через JSON:


ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураПараметров);
СтрокаКлюч = ЗаписьJSON.Закрыть();

ОткрытьФорму("ОбщаяФорма.МояФорма", ПараметрыФормы, , СтрокаКлюч);

Важный нюанс: если ваша структура содержит 50 и более полей, результирующая строка может стать слишком длинной. В таких случаях целесообразно использовать хеширование (например, MD5), чтобы получить строку фиксированной длины, которая будет однозначно идентифицировать ваш набор параметров.

Решение 3: Обработка события «ПриПовторномОткрытии»

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

Чтобы обновить данные в форме, необходимо обязательно использовать обработчик ПриПовторномОткрытии(Параметры) в модуле формы. Проанализируем, как это работает: в этот обработчик передается структура параметров, которую вы отправили в метод ОткрытьФорму. Здесь вы должны программно обновить реквизиты формы.


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

Программный поиск окон через «ПолучитьОкна»

В некоторых сложных случаях стандартный параметр Уникальность может быть недостаточно гибким. Например, если логика сравнения параметров подразумевает игнорирование некоторых полей. Тогда мы можем пойти по пути ручного управления окнами.

Разберем алгоритм поиска:

  1. Используем метод ПолучитьОкна() для получения списка всех открытых окон приложения.
  2. В цикле анализируем содержимое окон. Если свойство Содержимое[0] является нужной нам формой, проверяем её параметры.
  3. Если форма найдена — вызываем метод Активизировать().
  4. Если форма не найдена — открываем новую.

Этот способ более трудоемкий, но он дает 100% контроль над процессом поиска дублей, позволяя реализовывать самую причудливую логику сравнения данных.

Подведем итоги

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

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

← На главную