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