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