В практике разработки на платформе 1С:Предприятие нередко возникают задачи построения сложных динамических интерфейсов — например, когда состав или порядок строк одной табличной части (ТЧ1) напрямую определяет структуру колонок другой таблицы (ТЧ2, сводной таблицы или матрицы показателей). При интерактивном изменении порядка строк пользователем с помощью стандартных кнопок перемещения («Переместить вверх» / «Переместить вниз») требуется зафиксировать факт сдвига и синхронно перестроить зависимые колонки.
Рассмотрим особенности платформы, возникающие сложности и несколько способов решения этой задачи: от использования встроенных событий формы до создания полностью контролируемых пользовательских команд.
Проанализируем базовую проблему: у элемента формы Таблица отсутствуют специализированные события вроде ПередПеремещениемСтроки или ПослеПеремещенияСтроки. При вызове стандартных команд перемещения платформа сама меняет порядок элементов в коллекции и пересчитывает свойство НомерСтроки.
Если мы попытаемся связать колонки зависимой таблицы исключительно со свойством НомерСтроки, то неизбежно столкнемся с рассинхронизацией. Кроме того, событие ПриАктивизацииСтроки вызывается не только перед перемещением, но и при любом изменении фокуса, переходе клавишами со стрелками или открытии формы, что требует осторожного подхода к сохранению промежуточного состояния.
Разберем вариант, основанный на фиксации позиции активной строки в контексте формы и последующей обработке события изменения таблицы.
&НаКлиенте
Процедура ДисциплиныПриАктивизацииСтроки(Элемент)
Если Элемент.ТекущиеДанные <> Неопределено Тогда
НомерСтрокиДоПеремещения = Элемент.ТекущиеДанные.НомерСтроки;
КонецЕсли;
КонецПроцедуры
ПриИзменении. В этот момент данные уже обновлены, и текущая строка имеет новый номер:
&НаКлиенте
Процедура ДисциплиныПриИзменении(Элемент)
Если Элемент.ТекущиеДанные <> Неопределено Тогда
НомерСтрокиПослеПеремещения = Элемент.ТекущиеДанные.НомерСтроки;
СместитьКолонкиСводнойТаблицы(НомерСтрокиДоПеремещения, НомерСтрокиПослеПеремещения);
КонецЕсли;
КонецПроцедуры
Рассмотрим более надежный и контролируемый подход. Использование стандартных команд панели может быть подвержено сбоям при быстрой серии кликов. Переопределение кнопок на собственные команды формы дает полный контроль над индексами строк до и после выполнения операции.
Разберем реализацию по шагам:
ПереместитьВверх и ПереместитьВниз.КомандаПереместитьВверх и КомандаПереместитьВниз, добавляем для них кнопки на панель.Сдвинуть() коллекции ДанныеФормыКоллекция:
&НаКлиенте
Процедура КомандаПереместитьВверх(Команда)
ТекущиеДанные = Элементы.Дисциплины.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИндексТекущей = Объект.Дисциплины.Индекс(ТекущиеДанные);
Если ИндексТекущей > 0 Тогда
// Сдвигаем строку вверх в основной таблице
Объект.Дисциплины.Сдвинуть(ИндексТекущей, -1);
// Синхронизируем зависимую таблицу для пары известных индексов
СинхронизироватьКолонки(ИндексТекущей, ИндексТекущей - 1);
КонецЕсли;
КонецПроцедуры
Этот метод исключает зависимость от порядка вызова платформенных событий и гарантирует точное совпадение исходного и целевого индексов.
Посмотрим на ситуацию с точки зрения оптимизации интерфейса. Если вторая таблица уже содержит созданные элементы управления (колонки формы), для изменения их порядка не обязательно заново перестраивать всю таблицу через серверный контекст. Достаточно изменить визуальный порядок элементов формы на клиенте с помощью метода Элементы.Переместить():
&НаКлиенте
Процедура ПереместитьКолонкуФормы(ИмяКолонки, ИмяКолонкиПередКоторойВставить)
КолонкаДляПеремещения = Элементы[ИмяКолонки];
КолонкаОриентир = Элементы[ИмяКолонкиПередКоторойВставить];
Элементы.Переместить(КолонкаДляПеремещения, Элементы.ТЧ2, КолонкаОриентир);
КонецПроцедуры
Важный момент: Чтобы связь между строками первой таблицы и колонками второй не зависела от порядка их расположения, рекомендуется использовать уникальные строковые ключи или идентификаторы строк (получаемые через свойство ТекущаяСтрока и метод НайтиПоИдентификатору()). В таком случае колонка второй таблицы связывается не с номером позиции, а с постоянным ключом строки, что полностью исключает потерю данных при любых сортировках и перестановках.