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