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