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