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