Почему при обращении к реквизиту управляемой формы возвращается пустая строка вместо значения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 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, платформа обращается к системному свойству заголовка окна, а не к созданному нами реквизиту. Поскольку заголовок формы явно не был задан программно, платформа возвращает его значение по умолчанию — пустую строку.

Почему отладчик показывает разные данные

Многих разработчиков сбивает с толку поведение табло и дерева переменных в отладчике. Разберем по шагам, почему возникает путаница:

  1. Когда мы раскрываем ветку ЭтаФорма или ЭтотОбъект целиком, среда отладки опрашивает коллекцию метаданных реквизитов формы. В этом списке отображаются данные именно реквизита: виден ссылочный тип и выбранный элемент справочника.
  2. Когда же мы вычисляем конкретное выражение ЭтаФорма.Title, компилятор платформы обращается к контексту формы по стандартным правилам разрешения имен и находит системное свойство Заголовок, скрывающее реквизит.

Как решить проблему и получить значение реквизита

На стороне клиента у управляемой формы отсутствует возможность динамического обращения к реквизитам по строковому ключу (конструкция вида ЭтаФорма["Title"] не поддерживается). Поэтому единственным надежным решением является переименование пользовательского реквизита.

Изменим имя реквизита в редакторе формы (например, назовем его по-русски Должность или добавим английский префикс JobTitle / RefTitle), после чего скорректируем код:


&НаКлиенте
Процедура Save(Команда)
    Поля = Новый Структура;
    Поля.Вставить("name", ЭтаФорма.name);
    Поля.Вставить("name2", ЭтаФорма.name2);
    Поля.Вставить("TelNo", ЭтаФорма.TelNo);
    Поля.Вставить("FaxNo", ЭтаФорма.FaxNo);
    Поля.Вставить("Position", ЭтаФорма.Position);
    Поля.Вставить("Title", ЭтаФорма.JobTitle); // Обращаемся к переименованному реквизиту
    Поля.Вставить("Email", ЭтаФорма.Email);
    
    ЭтаФорма.Закрыть(Поля);
КонецПроцедуры

Теперь обращение ЭтаФорма.JobTitle вернет ожидаемую ссылку на справочник без каких-либо конфликтов с платформенными свойствами.

Часто встречающиеся коллизии имен в управляемых формах

Посмотрим на список наиболее коварных английских имен, которые нельзя использовать для реквизитов и реквизитов-объектов, чтобы избежать их затенения встроенными свойствами формы:

  1. Title — перекрывает свойство Заголовок (всегда имеет тип «Строка»).
  2. Parameters — перекрывает свойство Параметры формы.
  3. ReadOnly — перекрывает свойство ТолькоПросмотр (тип «Булево»).
  4. Owner или FormOwner — перекрывает свойство ВладелецФормы.
  5. Items — конфликтует с коллекцией Элементы.
  6. Commands — перекрывает системную коллекцию Команды.
  7. Modified — перекрывает признак Модифицированность.
  8. CurrentItem — скрывает свойство ТекущийЭлемент.
  9. Window — перекрывает объект Окно формы.
  10. Key — конфликтует с ключом записи в формах регистров и расширений.

Чтобы полностью исключить подобные накладки при проектировании управляемых форм, рекомендуется придерживаться единого стандарта разработки: называть реквизиты осмысленными русскоязычными именами либо использовать специализированные префиксы, а также регулярно запускать синтаксический контроль и статическую проверку конфигурации.

Рекомендации по возврату данных из закрываемой формы

В исходном коде диалог закрывается с передачей структуры данных: ЭтаФорма.Закрыть(Поля). Рассмотрим, как правильно принять этот результат в вызывающей форме в соответствии со стандартами разработки 1С.

Использование модальных вызовов в современном интерфейсе 1С:Предприятия не рекомендуется, так как они блокируют работу в веб-клиенте и мобильных приложениях. Правильный подход предполагает применение механизма асинхронных оповещений.

Посмотрим на пример открытия формы с последующей обработкой возвращенного результата:


&НаКлиенте
Процедура ВвестиКонтакты(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормыКонтактов", ЭтотОбъект);
    ОткрытьФорму("ОбщаяФорма.ФормаВводаКонтактов", , ЭтотОбъект, , , , Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияФормыКонтактов(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = Неопределено Тогда
        // Пользователь закрыл окно крестиком или отказался от ввода
        Возврат;
    КонецЕсли;
    
    // Результат содержит переданную структуру Поля
    ВыбраннаяСсылка = Результат.Title;
    Сообщить("Выбран элемент: " + Строка(ВыбраннаяСсылка));
КонецПроцедуры

Если же форма предназначена исключительно для выбора одного значения, стандартным решением является использование процедуры ОповеститьОВыборе(ЗначениеВыбора) вместо явного формирования структуры, что позволяет вызывающей форме штатно обработать выбор в процедуре ОбработкаВыбора.

← На главную