При работе с интерфейсом 1С часто возникает задача автоматизации заполнения иерархических структур. Типичный сценарий: пользователь выбирает в строке ДереваЗначений группу справочника, и система должна мгновенно «подтянуть» все элементы, входящие в эту группу, в виде подчиненных строк. В данной статье мы разберем, какие события платформы 1С:Предприятие 8 подходят для этой задачи и как их правильно использовать в зависимости от способа ввода данных.
Прежде всего, проанализируем ситуацию. Пользователь может взаимодействовать с деревом двумя основными способами:
Для каждого из этих случаев предусмотрены свои обработчики событий, которые позволяют перехватить действие и выполнить программный код по заполнению дерева.
Если ваша основная цель — реагировать на выбор значения в конкретной ячейке (например, в колонке «Номенклатура» или «Объект»), то самым надежным способом будет использование события ПриИзменении. Обратите внимание, что это событие элемента формы, который находится внутри колонки, а не самой таблицы.
Рассмотрим по шагам, как реализовать этот механизм:
ПриИзменении.Посмотрим на пример кода, который реализует эту логику:
&НаКлиенте
Процедура ДеревоНоменклатураПриИзменении(Элемент)
ТекущиеДанные = Элементы.Дерево.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Вызываем серверную процедуру для анализа и заполнения
ЗаполнитьПодчиненныеЭлементыНаСервере(ТекущиеДанные.Идентификатор());
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьПодчиненныеЭлементыНаСервере(ИдентификаторСтроки)
// Получаем объект строки дерева по идентификатору
СтрокаДерева = Дерево.НайтиПоИдентификатору(ИдентификаторСтроки);
// Проверяем, является ли выбранное значение группой
Если ЗначениеЗаполнено(СтрокаДерева.Номенклатура) И СтрокаДерева.Номенклатура.ЭтоГруппа Тогда
// Очищаем старые подчиненные элементы, если они были
ПодчиненныеЭлементы = СтрокаДерева.ПолучитьЭлементы();
ПодчиненныеЭлементы.Очистить();
// Запрос к базе данных для получения состава группы
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель = &Родитель";
Запрос.УстановитьПараметр("Родитель", СтрокаДерева.Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ПодчиненныеЭлементы.Добавить();
НоваяСтрока.Номенклатура = Выборка.Ссылка;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Иногда пользователю удобнее выбирать группу через стандартное окно подбора. В этом случае событие ПриИзменении сработает уже после того, как значение будет помещено в ячейку. Однако, если вам нужно более тонкое управление (например, вы хотите спросить пользователя: «Развернуть состав группы?»), лучше использовать событие таблицы ОбработкаВыбора.
Разберем ситуацию: когда пользователь выбирает значение в форме выбора справочника, управление передается в это событие. Здесь мы можем получить выбранное значение через параметр ЗначениеВыбора еще до того, как оно отобразится в интерфейсе.
Если вы хотите, чтобы при нажатии на кнопку «Добавить» (плюсик в командной панели) происходила особая логика, рассмотрите событие таблицы ПередНачаломДобавления.
Важный момент: если вы установите параметр Отказ = Истина в этом событии, стандартное создание пустой строки будет отменено, и вы сможете программно добавить свою структуру строк, вызвав метод Добавить() у коллекции Элементы дерева.
&НаКлиенте
Процедура ДеревоПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа)
// Если мы хотим полностью заменить логику добавления:
// Отказ = Истина;
// ... здесь вызываем свою форму выбора или модальное окно ...
КонецПроцедуры
Проанализируем ситуацию, когда дерево очень большое. Заполнять все группы сразу при выборе «родителя» может быть накладно для производительности системы. В 1С существует элегантное решение — ленивая загрузка.
Суть метода заключается в следующем:
ПриРазворачивании. Оно срабатывает в тот момент, когда пользователь нажимает на «плюс».Пример использования ПриРазворачивании:
&НаКлиенте
Процедура ДеревоПриРазворачивании(Элемент, ИдентификаторСтроки, Отказ)
Строка = Дерево.НайтиПоИдентификатору(ИдентификаторСтроки);
// Проверяем, не загружали ли мы данные ранее
Если Строка.ПолучитьЭлементы().Количество() = 1
И Строка.ПолучитьЭлементы()[0].Номенклатура = ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка") Тогда
// Вызываем сервер для реальной загрузки данных
ЗагрузитьДанныеУзлаНаСервере(ИдентификаторСтроки);
КонецЕсли;
КонецПроцедуры
Выбор конкретного события зависит от желаемого поведения интерфейса:
ПриИзменении элемента колонки.ОбработкаВыбора.ПриРазворачивании.Помните, что при работе с ДеревомЗначений на управляемых формах крайне важно правильно оперировать идентификаторами строк (метод Идентификатор()), так как сама ссылка на строку на клиенте и сервере может вести себя по-разному. Всегда старайтесь минимизировать количество серверных вызовов, передавая на сервер только необходимый идентификатор изменяемого узла.