Редактирование элемента справочника и записей регистра сведений в одной форме

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

ВЫ МОЖЕТЕ ПРЯМО СЕЙЧАС СКОПИРОВАТЬ ФОРМУ
НА ЖЕСТКИЙ ДИСК ВАШЕГО КОМПЬЮТЕРА

Копировать