При разработке интерфейсов на платформе «1С:Предприятие 8.3» программисты часто сталкиваются с необходимостью предоставить пользователю возможность множественного выбора элементов из списка. Стандартный метод ПоказатьОтметкуЭлементов() объекта СписокЗначений позволяет быстро вывести модальное или блокирующее окно с флажками (галочками). Однако у этого метода есть существенный недостаток: стандартное окно платформы жестко зафиксировано, и мы никак не можем программно добавить туда кастомные кнопки, например, «Выделить все» и «Снять все».
В этой статье мы подробно разберем, как решить эту задачу различными способами: от простых пользовательских лайфхаков до создания собственных форм и использования готовых инструментов Библиотеки стандартных подсистем (БСП).
Прежде чем приступать к написанию нового кода и созданию форм, давайте проанализируем стандартные возможности платформы «1С:Предприятие». Часто разработчики тратят часы на доработку конфигурации просто потому, что пользователи не знают о встроенных возможностях интерфейса.
В стандартном системном окне, которое открывается методом ПоказатьОтметкуЭлементов(), уже реализован механизм быстрого массового управления флажками с помощью клавиатуры:
После этого действия флажки установятся для абсолютно всех выделенных элементов. Повторное нажатие клавиши Пробел снимет выделение со всех строк. Если вашим пользователям достаточно такого решения, вы можете сэкономить время и отказаться от создания кастомных форм, просто проинструктировав их или добавив краткую подсказку в интерфейс.
Если требования бизнеса или стандарты юзабилити вашего проекта жестко требуют наличия физических кнопок на форме, нам придется отказаться от стандартного вызова ПоказатьОтметкуЭлементов() и спроектировать собственную форму выбора.
Для реализации этого решения выполним следующие шаги:
ФормаВыбораИзСписка.СписокЗначений (назовем его СписокДляВыбора) и вынесем его на элементную панель формы в виде таблицы. Убедимся, что у таблицы включено отображение флажков (свойство Пометка).ВыделитьВсеЭлементы и СнятьВсеВыделения. Разместим их в командной панели нашей таблицы.При написании обработчиков для этих команд начинающие разработчики часто совершают архитектурную ошибку: они начинают обходить список в цикле Для Каждого, чтобы вручную проставить значение Истина или Ложь в свойство Пометка. На больших списках (от нескольких сотен элементов и выше) такой обход работает крайне медленно из-за накладных расходов интерфейса.
Для быстрого управления пометками у объекта СписокЗначений существует встроенный высокопроизводительный метод, работающий непосредственно на уровне платформы. Рассмотрим пример правильного кода для модулей нашей формы:
&НаКлиенте
Процедура ВыделитьВсеЭлементы(Команда)
// Быстро устанавливаем галочки для всех элементов списка
СписокДляВыбора.ЗаполнитьПометки(Истина);
КонецПроцедуры
&НаКлиенте
Процедура СнятьВсеВыделения(Команда)
// Быстро снимаем галочки со всех элементов списка
СписокДляВыбора.ЗаполнитьПометки(Ложь);
КонецПроцедуры
Использование встроенного метода ЗаполнитьПометки() позволяет мгновенно обрабатывать списки любой длины без зависания интерфейса клиентского приложения.
Если вы разрабатываете решение на современных версиях платформы «1С:Предприятие 8» (начиная с релиза 8.3.18 и выше) и ваша конфигурация работает в режиме отказа от модальности, настоятельно рекомендуется использовать асинхронные вызовы.
Вместо устаревшего метода ПоказатьОтметкуЭлементов(), который требует передачи описания оповещения (колбэка), теперь мы можем использовать конструкцию Ждать совместно с методом ОтметитьЭлементыАсинх(). Это делает код линейным, избавляет от необходимости плодить лишние процедуры-обработчики в модуле и существенно повышает читаемость алгоритма. Для освоения таких подходов пригодятся рабочие примеры асинхронного вызова функций и процедур в БСП.
Рассмотрим, как выглядит вызов асинхронного метода выбора:
&НаКлиенте
Асинх Процедура ВыбратьАдресаДляРассылки()
СписокАдресов = ПолучитьСписокПочтовыхАдресовНаСервере();
// Вызываем асинхронное окно разметки элементов
РезультатВыбора = Ждать СписокАдресов.ОтметитьЭлементыАсинх("Выберите адреса получателей");
Если РезультатВыбора <> Неопределено Тогда
// РезультатВыбора содержит список значений с установленными пометками
Для Каждого Элемент Из РезультатВыбора Цикл
Если Элемент.Пометка Тогда
Сообщить("Выбран адрес: " + Элемент.Значение);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Этот код лаконичен, безопасен для веб-клиента и полностью соответствует современным стандартам разработки фирмы «1С».
Зачем изобретать велосипед и тратить время на рисование собственных диалоговых окон, если в вашей конфигурации установлена БСП (Библиотека стандартных подсистем)? В типовых решениях (таких как УТ, ERP, КА, УНФ) уже есть отличные универсальные формы, спроектированные специально для решения подобных задач.
Например, в составе БСП присутствует общая форма ВыборЭлементов (в некоторых старых редакциях она может называться ФормаВводаЗначений или СписокЗначенийОтбора). На этой форме разработчики БСП уже заботливо разместили все необходимые элементы управления: командную панель с кнопками «Установить все пометки», «Снять все пометки», а также механизмы поиска, сортировки и подбора. Для быстрого поиска примеров вызова различных функций и форм подсистем пригодится справочник по методам БСП.
Давайте разберем пример, как программно вызвать готовую форму БСП, передать туда наш список значений для отметки галочками и получить результат обратно:
&НаКлиенте
Процедура ВыбратьЭлементыЧерезБСП()
// Заполняем исходный список значений данными
ПараметрыСписка = Новый СписокЗначений;
ПараметрыСписка.Добавить("Адрес_1", "Офис на Севере", Ложь);
ПараметрыСписка.Добавить("Адрес_2", "Склад Центр", Истина);
ПараметрыСписка.Добавить("Адрес_3", "Филиал Запад", Ложь);
// Формируем параметры для открытия общей формы БСП
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СписокЗначений", ПараметрыСписка);
ПараметрыФормы.Вставить("Заголовок", "Выберите склады для инвентаризации");
// Задаем описание оповещения для обработки результата
Оповещение = Новый ОписаниеОповещения("ПослеВыбораЭлементовБСП", ЭтотОбъект);
// Открываем готовую форму выбора из состава БСП
ОткрытьФорму("ОбщаяФорма.ВыборЭлементов", ПараметрыФормы, ЭтотОбъект,,,, Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораЭлементовБСП(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора <> Неопределено Тогда
// В РезультатВыбора возвращается измененный список значений
Для Каждого Элемент Из РезультатВыбора Цикл
Если Элемент.Пометка Тогда
ПоказатьПредупреждение(, "Выбран элемент: " + Элемент.Представление);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Использование готовых форм БСП существенно сокращает время разработки, снижает количество ошибок в коде и обеспечивает единый, привычный для пользователей интерфейс во всей системе.
В ходе обсуждения на форуме разработчики затронули интересную идею: что делать, если нужно отмечать галочками элементы справочника прямо в динамическом списке на форме, имитируя работу списка значений? Динамический список работает на базе урезанной версии Системы компоновки данных (СКД), которая не умеет напрямую обрабатывать таблицы значений в качестве параметров. Тем не менее, эту задачу можно элегантно решить через передачу обычного массива отмеченных идентификаторов.
Давайте детально разберем эту логику:
&СписокОтмеченных.Запрос динамического списка в данном случае будет выглядеть следующим образом:
ВЫБРАТЬ
ВЫБОР
КОГДА СправочникСклады.Ссылка В (&СписокОтмеченных) ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК Отметка,
СправочникСклады.Ссылка КАК Ссылка,
СправочникСклады.Наименование КАК Наименование
ИЗ
Справочник.Склады КАК СправочникСклады
Если нам требуется программно получить список всех строк, которые в данный момент отображаются на экране пользователя с учетом наложенных им отборов (например, чтобы по нажатию кнопки «Выделить все» отметить именно видимые элементы), мы можем применить программный вывод схемы компоновки динамического списка. Рассмотрим этот сложный, но эффективный алгоритм:
&НаСервере
Процедура ОтметитьВсеСтрокиДинамическогоСпискаНаСервере()
// Получаем исполняемую схему и настройки текущего динамического списка формы
Схема = Элементы.СписокСклады.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.СписокСклады.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
// Инициализируем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
// Выводим данные в коллекцию через процессор вывода
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ДеревоРезультата = Новый ДеревоЗначений;
ПроцессорВывода.УстановитьОбъект(ДеревоРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Выгружаем полученные ссылки и помещаем их в массив отмеченных
ВсеСсылки = ДеревоРезультата.Строки.ВыгрузитьКолонку("Ссылка");
// Устанавливаем обновленный массив в параметры динамического списка
СписокСклады.Параметры.УстановитьЗначениеПараметра("СписокОтмеченных", ВсеСсылки);
КонецПроцедуры
Этот метод гарантирует, что даже при сложных интерактивных отборах, установленных пользователем в динамическом списке, вы сможете безошибочно определить состав видимых строк и корректно проставить для них признаки отметки.
Подводя итоги нашего разбора, дадим несколько практических советов по выбору оптимального пути реализации:
ОбщаяФорма.ВыборЭлементов. Это сэкономит время разработки и тестирования.ЗаполнитьПометки() вместо медленных циклов Для Каждого.ОтметитьЭлементыАсинх() и оператора Ждать.