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