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