1с как установить редактировать в диалоге
Время неумолимо идёт вперёд, а платформа 1С 8 бежит ещё быстрей этого времени.
Управляемые формы теперь называются "интерфейс ТАКСИ", модальные окна запрещены, а режим использования синхронных вызовов расширений и внешних компонент наглухо положил работоспособность большинства этих расширений и внешних компонент, и половину старых методов в добавок.
В общем, пацаны, дела такие - многие из вас читали статью великолепного Чистова П. о работе с файлами в 8.3
Если Вы ещё этого не сделали - бегом марш! (ссылка)
Суть механизма работы с файлами в кратце:
1) На клиенте выбираем файл
2) Пихаем его в чёрный ящик
3) Сохраняем содержимое чёрного ящика на сервере
Загвоздка состоит в том, что делать это надо особенно, по-новому и с душой.
и прочие языческие штучки здесь не прокатят.
Вот листинг кода, который позволяет загрузить файл с клиента
Нас интересует метод "НачатьПомещениеФайлов", который, собственно, вызывает диалог выбора файла и помещает этот файл во временное хранилище. Заморачиваться с описанием временного хранилища нет смысла, просто запомните - это то место, куда помещаются все выбранные нами файлы в виде двоичных данных (черный ящик).
Понять, что там и как храниться в этом временном хранилище практически невозможно. Можно только обратиться к нашему файлу по навигационной ссылке, которая присваивается автоматически (см. переменную "Адрес").
С тем, что файлы нужно хранить в реквизите или ресурсе с типом "Хранилище значения", спорить, думаю, никто не будет. Достать файл из временного хранилища и поместить его в реквизит с типом "Хранилище значения" можно след.образом:
С одним разобрались, теперь второе - как достать файл из этого хранилища значений (которое, напомню, находится на сервере) и сохранить на диск клиента?
Прежде всего, нам надо получить навигационную ссылку на реквизит с типом "Хранилище значения", куда у нас помещается файл в виде бинарных данных.
Будьте, внимательны! Эта навигационная ссылка уже не имеет с временным хранилищем ничего общего! Проверить тип навигационной ссылки можно методом
По традиции, листинг кода, который вызывает диалог сохранения файла
Значение переменной "Файл" это ещё одна особенность данного способа. Здесь стоит обратить внимание на "ИмяФайла". Дело в том, что помещая файл во временное хранилище, информация о его имени и расширении теряется. Поэтому не забудьте где-нибудь сохранять корректное имя файла, или хотя бы его расширение, чтобы потом не мучаться с вопросом "А это вордовский документ или мп3?"
Метод "НачатьПолучениеФайлов" аналогичен методу "НачатьПомещениеФайлов". Просто один открывает диалог для выбора файла, другой же, наоборот, открывает диалог для сохранения файла.
При использовании данного способа, никакие совместимости модальности и синхронных вызовов в свойствах конфигурации устанавливать не нужно.
В 8.2 эту возможность убрали из целей производительности, Максим Радченко пишет в своей книге:
В версии 8.2 не поддерживается режим редактирования ссылочных данных информационной базы в списке. Данные можно редактировать только в форме.
При работе в режиме управляемого приложения свойство объекта конфигурации Способ редактирования игнорируется, и данные редактируются всегда в отдельной форме.
Это относится ко всем таблицам, источником данных которых является динамический список.
Если же таблица имеет другой источник данных (табличная часть, дерево значений и т.д.), то ее данные редактируются непосредственно в списке
В обычных формах, программно можно установить режим редактирования в списке
Для Регистра Сведений или Справочника - открыть палитру Свойства - закладка - представление - установить способ редактирования В Списке
Похожие FAQ
Еще в этой же категории
Как в форме списка реализовать сортировку по своему реквизиту? 10Если реквизит примитивного типа, то достаточно установить для свойства реквизита «Индексировать» значение «Индексировать» или «Индексировать с доп. упорядочиванием» (не доступно для реквизитов типа ХранилищеЗначения). Если же реквизит ссылочного типа Сортировка списка по произвольной колонке? 7
В процедуру ПриОткрытии или в конец модуля добавить: ЭлементыФормы.РегистрСведенийСписок.НастройкаПорядка.НомерСоглашения.Доступность=Истина; Где НомерСоглашения - Колонка в списке регистра сведений по которой нужно сортировать! Далее щелкнув Оформление строки в ПриПолученииДанных или ПриВыводеСтроки 6
Событие ПриПолученииДанных использется для оформления ячеек строк данных, отображаемых табличным полем. Обработчик данного события вызывается табличным полем в тех же случаях, что и обработчик ПриВыводеСтроки , т.е. при обновлении данных, отображ Табличное поле
Как получить строки табличного поля, отобранные отбором? 4
ОтборСтрок = ТабличнаяЧастьИсточник.ОтборСтрок ; ПостроительЗапроса = Новый ПостроительЗапроса; ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабличнаяЧастьИсточник); // Добавляются необходимые отборы, такие же как в отбор Отбор по списку значений 3
СозданныйСписок = Новый СписокЗначений; СозданныйСписок.Добавить(Перечисления.СтатусЗаявки.Выполнено); СозданныйСписок.Добавить(Перечисления.СтатусЗаявки.ЗакрытиеЗаявки); СозданныйСписок.Добавить(Перечисления.СтатусЗаявки.ОтклоненаРукОтдЗакупок); Посмотреть все в категории Список Справочника, Документов, Регистров
Редактирование элемента справочника и записей регистра сведений в одной форме
Рассмотрим задачу создания формы, которая позволит редактировать номенклатуру и одновременно ее цены. Для решения этой задачи используем информационную базу демонстрационного примера Web-расширения.
Для упрощения будем считать, что существует три типа цен: оптовая, мелкооптовая и розничная. В случае создания универсального решения (т.е. количество типов цен заранее неизвестно) необходимо будет динамически создавать элементы управления для редактирования цен. Тем не менее, продемонстрированный в данном разделе подход применим и в этом случае.
С помощью Помощника создаем в среде Visual Studio новый проект; в качестве базы данных выберем информационную базу Демонстрационного примера Web-расширения.
Далее, воспользовавшись шаблоном V8ListForm , создаем форму списка для справочника "Номенклатура". Полученную форму устанавливаем как стартовую форму приложения.
Используя шаблон V8ItemForm , создаем форму элемента справочника "Номенклатура". В списке полей для размещения в диалоге Помощника выбираем следующие поля:
Теперь необходимо добавить источники данных для цен номенклатуры. Для этого в форме размещаем три элемента управления V8RecordDataSource . Элемент управления V8RecordDataSource предназначен для работы с записями регистров. В окне Properties задаем свойства этих элементов управления:
Свойство | Значение |
---|---|
ID | DSОптоваяЦена |
InitByRequest | False |
TableName | РегистрСведений.ЦеныНоменклатуры |
Свойство | Значение |
---|---|
ID | DSМелкоОптоваяЦена |
InitByRequest | False |
TableName | РегистрСведений.ЦеныНоменклатуры |
Свойство | Значение |
---|---|
ID | DSРозничнаяЦена |
InitByRequest | False |
TableName | РегистрСведений.ЦеныНоменклатуры |
Значение свойства InitByRequest мы устанавливаем равным False , так как параметры, которые будут передаваться в эту форму через строку запроса (значение ключевого поля, например), относятся в элементу справочника "Номенклатура", а не к регистру сведений.
У каждого из элементов управления V8RecordDataSource в коллекцию Fields необходимо добавить элемент со свойством Name – Цена . Именно это поле мы будем редактировать при помощи нашей формы.
Далее в таблицу, в которой размещены поля ввода, добавляем три строки. В первой колонке этих строк указываем наименование типа цен: «Оптовая цена», «Мелкооптовая цена», «Розничная цена», а во второй колонке размещаем три элемента управления V8TextBox , у которых устанавливаем следующие значения свойств:
Свойство | Значение |
---|---|
ItemDataSource | DSОптоваяЦена |
FieldName | Цена |
Свойство | Значение |
---|---|
ItemDataSource | DSМелкоОптоваяЦена |
FieldName | Цена |
Свойство | Значение |
---|---|
ItemDataSource | DSРозничнаяЦена |
FieldName | Цена |
Таким образом, мы связали поля ввода ( V8TextBox ) с источниками данных ( V8RecordDataSource ).
Теперь необходимо обеспечить синхронизацию источников данных.
В первую очередь напишем метод, который заполняет значения ключевых полей (измерений) для источников данных регистра сведений.
private void FillValues()
DSОптоваяЦена.KeyValues = new object[2];
DSМелкоОптоваяЦена.KeyValues = new object[2];
DSРозничнаяЦена.KeyValues = new object[2];
DSОптоваяЦена.KeyValues[0] = ItemDataSource.KeyValue;
DSМелкоОптоваяЦена.KeyValues[0] = ItemDataSource.KeyValue;
DSРозничнаяЦена.KeyValues[0] = ItemDataSource.KeyValue;
V8DbSelectCommand command = new V8DbSelectCommand();
command.Connection = ItemDataSource.Connection;
bool needClose = ItemDataSource.Connection.State == ConnectionState.Closed;
if (ItemDataSource.Connection.State == ConnectionState.Closed)
ItemDataSource.Connection.Open();
try
command.CommandText = "SELECT Ссылка FROM Справочник.ТипыЦен WHERE Наименование=\"Оптовая\"";
DSОптоваяЦена.KeyValues[1] = command.ExecuteScalar();
command.CommandText = "SELECT Ссылка FROM Справочник.ТипыЦен WHERE Наименование=\"Мелкооптовая\"";
DSМелкоОптоваяЦена.KeyValues[1] = command.ExecuteScalar();
command.CommandText = "SELECT Ссылка FROM Справочник.ТипыЦен WHERE Наименование=\"Розничная\"";
DSРозничнаяЦена.KeyValues[1] = command.ExecuteScalar();
>
finally
if (needClose)
ItemDataSource.Connection.Close();
>
>
В этом методе для каждого источника данных мы создаем массив для хранения значений ключевых полей. Массив содержит два элемента, по числу измерений регистра сведений "ЦеныНоменклатуры" ("Номенклатура" и "ТипЦен"). Значением измерения "Номенклатура" является ссылка на редактируемый в этой форме элемент справочника "Номенклатура". Значение этой ссылки содержится в свойстве KeyValue источника данных ItemDataSource .
Значения для измерения "ТипЦен" мы получаем при помощи запроса, воспользовавшись объектом V8DbSelectCommand для каждого типа цен.
Это метод мы будем использовать для инициализации источников данных при редактировании номенклатуры или создании новой.
Далее создаем обработчик OnInitObject элемента управления ItemDataSource . Это событие возникает при создании нового элемента справочника "Номенклатура".
private void ItemDataSource_OnInitObject(object source, _1C.V8.WebControls.V8ItemDataSourceInitObjectEventArgs e)
FillValues();
DSОптоваяЦена.Connection = ItemDataSource.Connection;
DSОптоваяЦена.InitNew();
DSМелкоОптоваяЦена.Connection = ItemDataSource.Connection;
DSМелкоОптоваяЦена.InitNew();
DSРозничнаяЦена.Connection = ItemDataSource.Connection;
DSРозничнаяЦена.InitNew();
>
В этом обработчике мы заполняем значения ключевых полей источников данных регистра и, используя соединение «ведущего» источника данных ( ItemDataSource ), инициализируем их.
Стоит обратить внимание на использование свойства Connection «ведущего» источника данных. Данная техника является предпочтительной, так как сокращает количество COM-соединений с 1С:Предприятием, а также позволяет осуществлять запись данных в одной транзакции.
Теперь напишем метод для синхронизации чтения данных. Для этого создаем обработчик события OnRead элемента управления ItemDataSource .
private void ItemDataSource_OnRead(object source, System.EventArgs e)
FillValues();
DSОптоваяЦена.Connection = ItemDataSource.Connection;
DSОптоваяЦена.Read(DSОптоваяЦена.KeyValues);
if (DSОптоваяЦена.dataSet.Tables[0].Rows.Count == 0)
DSОптоваяЦена.InitNew();
DSМелкоОптоваяЦена.Connection = ItemDataSource.Connection;
DSМелкоОптоваяЦена.Read(DSМелкоОптоваяЦена.KeyValues);
if (DSМелкоОптоваяЦена.dataSet.Tables[0].Rows.Count == 0)
DSМелкоОптоваяЦена.InitNew();
DSРозничнаяЦена.Connection = ItemDataSource.Connection;
DSРозничнаяЦена.Read(DSРозничнаяЦена.KeyValues);
if (DSРозничнаяЦена.dataSet.Tables[0].Rows.Count == 0)
DSРозничнаяЦена.InitNew();
>
После чтения данных (метод Read() ), мы проверяем, что источник содержит данные, т.е., что для этой номенклатуры есть цена для заданного типа цен. Если цены нет, то мы инициализируем соответствующий источник данных.
Значения цен необходимо отобразить на форме. Создаем обработчик события BeforeSetDataToForm элемента управления V8ItemDataSource .
private void ItemDataSource_BeforeSetDataToForm(object source, System.EventArgs e)
DSОптоваяЦена.SetDataToForm();
DSМелкоОптоваяЦена.SetDataToForm();
DSРозничнаяЦена.SetDataToForm();
>
Переходим к процессу записи данных. В первую очередь необходимо значения ключевых полей исотчников данных регистра перенести в записываемый набор данных. Для каждого элемента управления V8RecordDataSource создаем обработчик события BeforeWrite .
private void DSОптоваяЦена_BeforeWrite(object source, System.EventArgs e)
DataRow row = DSОптоваяЦена.dataSet.Tables[0].Rows[0];
row["Номенклатура"] = ItemDataSource.KeyValue;
row["ТипЦен"] = DSОптоваяЦена.KeyValues[1];
>
private void DSМелкоОптоваяЦена_BeforeWrite(object source, System.EventArgs e)
DataRow row = DSМелкоОптоваяЦена.dataSet.Tables[0].Rows[0];
row["Номенклатура"] = ItemDataSource.KeyValue;
row["ТипЦен"] = DSМелкоОптоваяЦена.KeyValues[1];
>
private void DSРозничнаяЦена_BeforeWrite(object source, System.EventArgs e)
DataRow row = DSРозничнаяЦена.dataSet.Tables[0].Rows[0];
row["Номенклатура"] = ItemDataSource.KeyValue;
row["ТипЦен"] = DSРозничнаяЦена.KeyValues[1];
>
Данные находятся в объекте dataSet источника данных. Значение измерения Номенклатура мы берем из «ведущего» источника данных, так как это значение могло измениться (в случае записи нового элемента справочника "Номенклатура").
Последний метод, который мы должны реализовать – это обработчик события OnWrite элемента управления ItemDataSource . Этот обработчик вызывается после сохранения данных «ведущего» источника данных.
private void ItemDataSource_OnWrite(object source, System.EventArgs e)
try
DSОптоваяЦена.Connection = ItemDataSource.Connection;
DSОптоваяЦена.doSave();
DSМелкоОптоваяЦена.Connection = ItemDataSource.Connection;
DSМелкоОптоваяЦена.doSave();
DSРозничнаяЦена.Connection = ItemDataSource.Connection;
DSРозничнаяЦена.doSave();
>
catch (Exception ex)
V8WebUtil.RegisterShowErrorScript(ex.GetBaseException().Message, this, false);
>
>
В этом методе мы вызываем сохранение данных источников регистра сведений, используя соединение «ведущего» источника. Таким образом, запись данных происходит в одной транзакции. В случае возникновения ошибки мы регистрируем скрипт для ее отображения.
В результате мы получили форму, с помощью которой мы можем создавать и редактировать записи справочника "Номенклатура", одновременно редактируя ее цены.
Файлы формы ( V8WebItemFrom1.aspx и V8WebItemForm1.aspx.cs ) находятся в каталоге \1CITS\EXE\Web
ВЫ МОЖЕТЕ ПРЯМО СЕЙЧАС СКОПИРОВАТЬ ФОРМУ
НА ЖЕСТКИЙ ДИСК ВАШЕГО КОМПЬЮТЕРА
Войдите как ученик, чтобы получить доступ к материалам школы
Внутренний язык программирования 1С 8.3 для начинающих программистов: использование диалогов в 1С
Автор уроков и преподаватель школы: Владимир Милькин
Давайте определимся, что же такое диалог? Вызов команды Сообщить является диалогом? А вызов команды ВвестиЧисло? А вызов ОткрытьЗначение?
Итак, диалог - это прежде всего элемент графического интерфейса , окно . А следовательно вызов Сообщить - диалогом не является, так как у него нет своего отдельного окна.
Диалог - это не просто окно. Это окно, которое открывается пользователю с целью вывода информации и (или) получения ответа.
Для того чтобы показать какой-либо диалог необходимо вызвать команду соответствующую этому диалогу и передать ей необходимые параметры. Команда - это обычная процедура или функция, только написанная не нами, а программистами фирмы 1С. Мы не можем менять эти команды, мы можем их только вызывать.
Предупреждение
Отличным примером диалога является вывод предупреждения пользователю:
Что мы видим? Вызов команды Предупреждение, в которую в качестве параметра передаётся строка "Осторожно".
Когда компьютер дойдёт до строчки, в которой вызывается эта команда, пользователю отобразится диалог предупреждения. И до тех пор, пока пользователь не закроет этот диалог, компьютер будет ожидать на этой же строчке. Только после закрытия диалога - выполнение программы продолжится и начнётся выполнение строки, следующей за вызовом диалога.
К примеру, пусть у нас есть такой код:
Как он будет выполняться?
В начале компьютер дойдёт до строчки №1 и выполнит команду Предупреждение с параметром "1". В этот момент пользователю покажется диалоговое окно с текстом "1", а компьютер замрёт на этой строчке и будет ожидать, пока пользователь закроет диалог. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
После закрытия диалога компьютер перейдёт к выполнению строчки №2 и выполнит команду Предупреждение уже с другим параметром "2". Пользователю снова покажется диалоговое окно, но уже с текстом "2", а компьютер замрёт уже на второй строчке и будет ожидать, пока пользователь закроет диалог.
Затем компьютер перейдёт к третьей строчке. Ну и так далее.
У команды Предупреждение параметр, отвечающий за текст, который выводится - не единственный. Есть ещё два дополнительных параметра:
Таймаут - означает количество секунд, через которое диалог закроется сам, если этого не сделает пользователь.
Заголовок - подменяет стандартный заголовок "1С:Предприятие" на строку пользователя.
К примеру, такой код:
покажет диалог с текстом "Осторожно." и заголовком "Внимание!", а также закроется через 5 секунд, если пользователь не сделает этого раньше:
А что если мы хотим задать только текст и заголовок окна, а таймаут не задавать?
Во-первых, мы можем передать в качестве таймаута ноль:
А во-вторых, мы можем просто оставить пустое место вместо параметра и система сама поймёт, что нужно оставить его значение по умолчанию:
Для того, чтобы узнавать обо всех возможных параметрах встроенных команд 1С - пользуйтесь синтакс-помощником так, как это описано в одном из предыдущих уроков (ссылка).
Ввод числа
Некоторые диалоги не только выводят какую-то информацию от нас пользователю, но и наоборот возвращают некий результат взаимодействия с пользователем. Примером такого диалога является ввод числа.
К примеру, напишем:
Зачем мы передаём в команду параметр Число? Во-первых, для того, чтобы отобразить начальное значение ввода в диалоге. А, во-вторых, чтобы вернуть в эту переменную значение, которое ввёл пользователь. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Но что если пользователь отказался от ввода и нажал кнопку "Отмена"? Как об этом узнать? Оказывается, функция ВвестиЧисло не только показывает диалог ввода числа, но ещё и возвращает нам Истина в том случае, если пользователь нажал кнопку "ОК" и Ложь, если он отменил ввод, нажав кнопку "Отмена".
Таким образом, более правильным будет такой код:
В переменную Результат (имя могло быть любым) возвращается Истина или Ложь в зависимости от того какую кнопку нажал пользователь ("ОК" или "Отмена").
В переменную Число возвращается число введенное пользователем.
Вопрос
Заключительным диалогом, который мы рассмотрим, будет является диалог вопроса пользователю.
Имя команды, которая вызывает этот диалог нам известна - Вопрос.
Теперь давайте посмотрим в синтакс-помощнике какие параметры принимает эта команда:
ТекстВопроса - это сам вопрос в текстовом виде, который увидит пользователь.
Кнопки - это одно из предопределенных значений, которые также можно посмотреть в синтакс-помощнике. Например, если передать в этот параметр:
- РежимДиалогаВопрос.ДаНет - в диалоге будет всего две кнопки Да и Нет.
- РежимДиалогаВопрос.ДаНетОтмена - три кнопки Да, Нет и Отмена.
- РежимДиалогаВопрос.ОкОтмена - две кнопки Ок и Отмена.
- И другие варианты кнопок.
- КодВозвратаДиалога.Нет
- КодВозвратаДиалога.Да
- КодВозвратаДиалога.Отмена
- И другие кнопки.
Таймаут - этот параметр нам уже знаком.
КнопкаПоУмолчанию - это кнопка, на которой будет фокус при показе окна. Её значения могут быть такими:
Заголовок - этот параметр нам уже знаком.
КнопкаТаймаута - если задать значение этой кнопки и параметр Таймаут, то именно на ней будет отображаться количество оставшихся секунд до закрытия диалога. У неё могут быть такие же значения как и у параметра КнопкаПоУмолчанию.
Уфф. Как видите, параметров много. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Но необязательно использовать их все. Как следует из синтакс-помощника обязательными к заполнению являются только первые два:
Вопрос-то мы задали. Хорошо бы теперь получить ответ - выспался пользователь или нет Из того же синтакс-помощника мы узнаём, что кнопка которая была нажата возвращается в качестве результата вызова команды Вопрос:
Модальность
Все примеры диалогов, которые мы рассмотрели - являются модальными, потому что компьютер, показывая диалог, замирает на той же строчке и не идёт дальше, пока диалог не закроется.
Ещё можно сказать, что когда мы показываем модальный диалог - пользователь может работать только с этим диалогом. Работа со всей остальной частью системы блокируется, пока не закроется диалог.
Таким недостатком не обладают немодальные версии диалогов, но к ним переходить нам ещё рано.
Читайте также: