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