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