# Урок 4. Редактирование списка



На прошлом уроке создали экран редактирования заказа, но реализацию возможности изменять клиента и редактировать позиции заказа оставил на этот урок.&#x20;

Скачайте архив с изображениями и разархивируйте его в папку проекта **\Template\Projects\1. Template\MobileForms\Images**.

{% file src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Flqa26kZ3wKBaAlqMnds6%2Flesson4-Images.zip?alt=media&token=d97ebe5b-8994-4ee8-a73f-815092db9b4b" %}



## Редактирование клиента <a href="#client-editing" id="client-editing"></a>

Так как список клиентов может быть большим и неудобным для использования ComboBox, то договорились для выбора клиента использовать отдельный экран. В прошлом уроке на экран редактирования заказа справа от поля с именем клиента добавили кнопку, которую планировали использовать для перехода на форму со списком клиентов. Самостоятельно создайте пустую форму списка клиентов и команду открытия этой формы, которая будет вызываться по ранее созданной кнопке:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="ClientSelectFormShowCommand" Type="FormShowCommand" Assembly="Commands">
  <Xml Type="Path">TemplateClientSelect.xml</Xml>
  <Show Type="None" />
  <Parameters>
    <Parameter Name="ClientId">
      <DataConnection SourceDataConnection="OrderPrimaryGetDataConnection">
        <Fields>
          <Field Name="ClientId" />
        </Fields>
      </DataConnection>
    </Parameter>
  </Parameters>
</Command>
```
{% endcode %}

Для удобства вызова списка клиентов, новую команду так же можно вызывать при клике по имени пользователя. Реализуйте эту возможность самостоятельно.

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

### Строка поиска <a href="#search-bar" id="search-bar"></a>

Чтобы пользователю было удобно работать с потенциально большим списком, добавим возможность поиска клиента по имени.

Строка поиска будет представлена объектом типа Panel с именем SearchPanel, содержащим элементы:

* SearchButton - хоть и является объектом типа Button, но это просто изображение лупы, не выполняющее никакой команды
* SearchTextBox - текстовое поле для ввода строки поиска
* ClearSearchButton - кнопка с изображением повернутого крестика для очистки строки поиска

Объект SearchPanel будет иметь настройки BorderCorner и BackColor аналогичные тем, что делали для панелей блоков на экране заказа. Высота панели 40 единиц.

Объект SearchButton будет иметь код:

{% code title="TemplateClientSelect.xml" %}
```xml
<MyObject Name="SearchButton" Type="Button" Assembly="BaseControls">
  <Top>2</Top>
  <Left>5</Left>
  <Height>35</Height>
  <Width>35</Width>
  <BackColor>
    <Object Name="SearchPanel">
      <Property Name="BackColor" />
    </Object>
  </BackColor>
  <BackgroundImage>Images\magnify.png</BackgroundImage>
  <BackgroundImageLayout>Zoom</BackgroundImageLayout>
</MyObject>
```
{% endcode %}

Самостоятельно создайте объект SearchTextBox, который будет справа от SearchButton без отступов. По высоте текстовое поле должно совпадать с высотой панели, следовательно отступ сверху будет нулевым. Ширина текстового поля должна учитывать размер кнопки ClearSearchButton и оставлять отступ справа в 10 единиц. Для объекта SearchTextBox текст-подсказки будет "Поиск". А его цвет зависит от оформления системы: для темной темы используется DarkGray, а для светлой темы - LightGray. Цвет основного текста (тэг `<ForeColor>`) тоже зависит от выбранного оформления системы: для темной темы используется  WhiteSmoke, а для светлой темы - MostlyBlack. Значение тэга `<BackColor>` можно тянуть из аналогичного свойства объекта SearchPanel. В тэге `<FontStyle>` укажем значение TextFont. По умолчанию TextBox имеет рамку, чтобы ее убрать используем тэг `<Multiline>` со значением True.

Кнопка ClearSearchButton для сброса значения объекта SearchTextBox будет иметь вид:

{% code title="TemplateClientSelect.xml" %}
```xml
<MyObject Name="ClearSearchButton" Type="Button" Assembly="BaseControls">
  <Top>5</Top>
  <Left>
    <Calculate>
      <Expression>{0} + 2</Expression>
      <Items>
        <Item>
          <Object Name="SearchTextBox">
            <Property Name="Right" />
          </Object>
        </Item>
      </Items>
    </Calculate>
  </Left>
  <Height>30</Height>
  <Width>30</Width>
  <BackColor>
    <Object Name="SearchPanel">
      <Property Name="BackColor" />
    </Object>
  </BackColor>
  <BackgroundImage>Images\close.png</BackgroundImage>
  <BackgroundImageLayout>Zoom</BackgroundImageLayout>
  <Commands>
    <Command Name="ResetSearchStringValueSetCommand" />
  </Commands>
</MyObject>
```
{% endcode %}

Самостоятельно создайте команду ResetSearchStringValueSetCommand.

Запустите приложение и проверьте отображение строки поиска на экране выбора клиента.

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FkoLP9RLVQwSbVhNkgJ7r%2F01_Search_Bar_Light_iOS.png?alt=media&#x26;token=568f732b-f9d1-43c7-85e1-fffa373f9ee4" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FmcNsNOK0Zz1kd2ETKpgk%2F01_Search_Bar_Dark_iOS.png?alt=media&#x26;token=9cd98c18-7609-4b68-b09c-e823340d9f30" alt="" width="311"><figcaption></figcaption></figure></div>

Отлично!

Самостоятельно добавьте на форму список с клиентами ClientCollectionView. В качестве источника данных используйте SecondaryGetDataConnection, в котором должны быть отфильтрованные по строке поиска данный из PrimaryGetDataConnection.

Запрос на получение списка клиентов должен содержать поля:&#x20;

В результате у вас должна получиться форма вида:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Fkj1MTaqttBCOATvoKCoO%2F02_Client_List_Light_iOS.png?alt=media&#x26;token=4cc42ff7-9d2a-4e5e-830d-c7d7ae974e7a" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2Fyz0ZO6mlPp8dVRVEUjLv%2F02_Client_List_Dark_iOS.png?alt=media&#x26;token=e5e12c57-a185-4bd9-918a-9a393464e7ba" alt="" width="311"><figcaption></figcaption></figure></div>

Запустите приложение и проверьте работу фильтра списка:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2F12oodBbnu8GFhbfQzhvW%2F03_Client_List_Filter_Light_iOS.png?alt=media&#x26;token=364b1bc7-9589-401e-a908-7c76f3a14773" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FWLCkMxWsibMxMLLsfPHw%2F03_Client_List_Filter_Dark_iOS.png?alt=media&#x26;token=b5faa750-30cb-4948-b3d1-8fb249050667" alt="" width="311"><figcaption></figcaption></figure></div>

### Выбор клиента

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

{% code title="TemplateClientSelect.xml" %}
```xml
<Parameter Name="ClientTitle" />
<Parameter Name="CityTitle" />
<Parameter Name="ClientEmail" />
<Parameter Name="ClientPhone" />
```
{% endcode %}

Добавьте команды типа ValueSetCommand, в которых всем параметрам формы, включая ClientId, присваиваются данные выбранного клиента.

&#x20;Все команды объединим в одну последовательность:

{% code title="TemplateClientSelect.xml" %}
```xml
<Command Name="SetParametersSequentialCommand" Type="SequentialCommand" Assembly="Commands">
  <Commands>
    <Command Name="ClientIdValueSetCommand" />
    <Command Name="ClientTitleValueSetCommand" />
    <Command Name="CityTitleValueSetCommand" />
    <Command Name="ClientEmailValueSetCommand" />
    <Command Name="ClientPhoneValueSetCommand" />
  </Commands>
</Command>
```
{% endcode %}

Добавим условие на изменение выбранной записи, в котором будем проверять значение get-проперти SelectedItemChanged:

{% code title="TemplateClientSelect.xml" %}
```xml
<Condition Name="CollectionViewSelectedItemChangedEqualCondition" Type="EqualCondition" Assembly="Conditions">
  <AlwaysChange Value="True" />
  <Items>
    <Item>
      <Object Name="ClientCollectionView">
        <Property Name="SelectedItemChanged" />
      </Object>
    </Item>
    <Item>True</Item>
  </Items>
</Condition>
```
{% endcode %}

На это условие создадим Execution, в котором будем сохранять данные в параметры, ставить флаг изменений и уходить с экрана выбора клиента:

{% code title="TemplateClientSelect.xml" %}
```xml
<Execution>
  <ConditionExpression>
    <Condition Name="CollectionViewSelectedItemChangedEqualCondition" />
  </ConditionExpression>
  <Commands>
    <Command Name="SetParametersSequentialCommand" />
    <Command Name="UpdatedTrueValueSetCommand" />
    <Command Name="FormCloseCommand" />
  </Commands>
</Execution>
```
{% endcode %}

Как видите на форме используем паттерн Updated - добавьте в файл параметр Updated и создайте команду для его обновления.

### Замена клиента в заказе

Вернемся в файл описания карточки заказа и реализуем обновления данных о клиенте в OrderPrimaryGetDataConnection. Самостоятельно создайте команду типа ValueSetCommand, в которой заменяйте значения в полях DataConnection соответствующих возвращаемым параметрам. Реализуйте Execution, в котором будет вызываться эта команда, используя паттерн Updated.

Запустите приложение и проверьте функциональность смены клиента в заказе.

Дополнительно: на кнопку смены клиента наложите ограничение, если заказ оплачен.

## Редактирование позиций заказа <a href="#edit-order-positions" id="edit-order-positions"></a>

Начнем с реализации возможности добавление позиций в заказ и изменение кол-ва товара в позиции. Для этого будем использовать отдельную форму со списком ТМЦ. А затем добавим удаление позиций с помощью свайпа в карточке заказа.

### Подготовка

Первым делом создадим [ConvertDataConnection](https://wfsys.gitbook.io/workflow-mobile-forms-syntax/workflow_mobile_forms/dataconnections/convert_dc), который будет преобразовывать OrderPositionPrimaryGetDataConnection:

{% code title="TemplateOrderEdit.xml" %}
```xml
<DataConnection Name="OrderPositionConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="OrderPositionPrimaryGetDataConnection" />
  <Fields>
    <Field Name="OrderPositionId" />
    <Field Name="MaterialId" />
    <Field Name="MaterialTitle" />
    <Field Name="MaterialCategoryTitle" />
    <Field Name="UnitPrice" />
    <Field Name="UnitPriceString" />
    <Field Name="TotalPrice" />
    <Field Name="Quantity" />
    <Field Name="QuantityString" />
    <Field Name="UnitShortTitle" />
    <Field Name="ID" Type="Value">
      <Object Name="CounterVariable" />
    </Field>
    <Field Name="Updated" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="Deleted" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="IsNew" Type="Value" DataType="BooleanDataType">False</Field>
  </Fields>
</DataConnection>
```
{% endcode %}

Здесь мы добавляем поле ID, которое будет временным идентификатором, который будем передавать на форму со списком товаров, чтобы правильно выставить флаги Added, Upated и Deleted. О них подробнее позже. Так же добавили поле IsNew, флаг которым будем помечать позиции заказа не сохраненные в базе данных.

В качестве значения нового поля указали объект CounterVariable, который является переменной-счетчиком и каждый раз при обращении увеличивает текущее значение на единицу и возвращает его.

{% code title="TemplateOrderEdit.xml" %}
```xml
<MyObject Name="CounterVariable" Type="CounterVariable" Assembly="WorkflowServer" ChangeForm="False">
  <Value />
</MyObject>
```
{% endcode %}

Укажем OrderPositionConvertDataConnection в качестве источника данных для объекта OrderPositionCollectionView.

Создадим форму, которую будем использовать для выбора товаров из каталога. Назовем ее TemplateMaterialList.xml.

Создадим команду для открытия новой формы:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="MaterialListFormShowCommand" Type="FormShowCommand" Assembly="Commands">
  <Xml Type="Path">TemplateMaterialList.xml</Xml>
  <Show Type="None" />
  <Parameters>
    <Parameter Name="MaterialArray">
      <DataConnection SourceDataConnection="OrderPositionConvertDataConnection">
        <Fields>
          <Field Name="ID" />
          <Field Name="MaterialId" />
          <Field Name="Quantity" />
          <Field Name="IsNew" />
        </Fields>
      </DataConnection>
    </Parameter>
  </Parameters>
</Command>
```
{% endcode %}

На форму каталога передаем параметр MaterialArray с массивом добавленных товаров в заказ.

На экране редактирования заказа добавьте кнопку _Изменить_, укажите для нее команду MaterialListFormShowCommand. Кнопку разместите справа над списком позиций заказов:



### Список товаров

Перейдем в файл новой формы и в него добавим строку поиска, как делали на форме выбора клиента.&#x20;

С родительской формы передаем параметр MaterialArray, добавим его на форму, а чтобы было удобно работать с передаваемым массивом данных создадим [ArrayGetDataConnection](https://wfsys.gitbook.io/workflow-mobile-forms-syntax/workflow_mobile_forms/dataconnections/array_get_dc):

{% code title="TemplateMaterialList.xml" %}
```xml
<DataConnection Name="MaterialArrayGetDataConnection" Type="ArrayGetDataConnection" Assembly="DataConnections">
  <Source>
    <Parameter Name="MaterialArray" />
  </Source>
  <Fields>
    <Field Name="ID" />
    <Field Name="MaterialId" />
    <Field Name="Quantity" DataType="IntegerDataType" />
  </Fields>
</DataConnection>
```
{% endcode %}

Создайте самостоятельно MaterialPrimaryGetDataConnection, который будет получать данные из запроса:

{% code title="Template.xml" %}
```xml
<SqlQuery Name="AppMaterialSelectSqlQuery">
  <Text>
    SELECT
      M.material_id AS "MaterialId",
      M.title AS "Title",
      M.material_category_id AS "MaterialCategoryId",
      MC.title AS "MaterialCategoryTitle",
      U.short_title AS "UnitShortTitle",
      M.unit_price AS "UnitPrice",
      trim(to_char(M.unit_price, '999G999G999D00')) || ' руб./' || U.short_title AS "UnitPriceString",
      M.material_id != ALL({MaterialId}::bigint[]) AS "NotUse",
      M.material_id = ANY({MaterialId}::bigint[]) AS "Selected"
    FROM
      template.material M
      LEFT JOIN template.material_category MC USING(material_category_id)
      LEFT JOIN template.unit U USING(unit_id)
    WHERE
      NOT M.archive OR M.material_id = ANY({MaterialId}::bigint[])
    ORDER BY M.title;
  </Text>
</SqlQuery>
```
{% endcode %}

В качестве параметра в запрос передаем массив MaterialId, полученных с родительской формы.

Здесь так же возвращаем два поля с ценой за единицу товара: UnitPrice и UnitPriceString - значение из первого будем возвращать на родительскую форму и использовать для расчета итоговой стоимости, а второе для отображения в карточке товара.

Так же возвращаем два флага:

* NotUse - true, если в заказе нет позиции с этим товаром, по этому флагу будет отображаться кнопка "Добавить" в карточке товара,
* Selected - true, если в заказе есть позиция с этим товаром, по этому флагу будет отображаться количество товара и кнопки изменения.

Обернем загружающее соединение в ConvertDataConnection и добавим новые поля:

{% code title="TemplateMaterialList.xml" %}
```xml
<DataConnection Name="MaterialConvertDataConnection" Type="ConvertDataConnection" Assembly="WorkflowServer">
  <SourceDataConnection Name="MaterialPrimaryGetDataConnection" />
  <Fields>
    <Field Name="MaterialId" />
    <Field Name="Title" />
    <Field Name="MaterialCategoryId" />
    <Field Name="MaterialCategoryTitle" />
    <Field Name="UnitShortTitle" />
    <Field Name="UnitPrice" />
    <Field Name="UnitPriceString" />
    <Field Name="Selected" />
    <Field Name="NotUse" />
    <Field Name="TotalPrice" />
    <Field Name="Quantity" Type="Substitution" Field="MaterialId">
      <DataConnection SourceDataConnection="MaterialArrayGetDataConnection">
        <Fields>
          <Field Name="MaterialId" />
          <Field Name="Quantity" />
        </Fields>
      </DataConnection>
    </Field>
    <Field Name="ID" Type="Substitution" Field="MaterialId">
      <DataConnection SourceDataConnection="MaterialArrayGetDataConnection">
        <Fields>
          <Field Name="MaterialId" />
          <Field Name="ID" />
        </Fields>
      </DataConnection>
    </Field>
    <Field Name="Added" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="Updated" Type="Value" DataType="BooleanDataType">False</Field>
    <Field Name="Deleted" Type="Value" DataType="BooleanDataType">False</Field>
  </Fields>
</DataConnection>
```
{% endcode %}

Поле TotalPrice необходимо для хранения итоговой суммы по выбранному товару.

В полях Quantity и ID подставляем соответствующие значения из массива полученного от родительской формы.

Поля Added, Updated и Deleted необходимы, чтобы при передачи на родительскую форму различать новые товары, которые нужно добавить через set-проперти AddRows, позиции в которых нужно обновить количество товара, и позиции подлежащие удалению из заказа.

Создайте MaterialCollectionView для отображения списка товаров. Добавьте в шаблон карточки элемента списка описание полей для наименования товара, его категории и цены за единицу.

Сразу создадим условие, в котором будем проверять наличие значения в поле ID:

{% code title="TemplateMaterialList.xml" %}
```xml
<Condition Name="SelectedIDIsNullOrEmptyCondition" Type="IsNullOrEmptyCondition" Assembly="Conditions">
  <AlwaysChange Value="True" />
  <Items>
    <Item>
      <Object Name="MaterialCollectionView">
        <Property Name="SelectedItemValueByFieldName">
          <Parameters>
            <Parameter Name="FieldName">ID</Parameter>
          </Parameters>
        </Property>
      </Object>
    </Item>
  </Items>
  <DataType Type="IntegerDataType" />
</Condition>
```
{% endcode %}

&#x20;Отлично, теперь можем реализовывать логику изменения позиций в заказе.

### Добавление товара

В шаблоне карточки списка товаров MaterialCollectionView опишем кнопку _Добавить_:

```xml
<TemplateItem Type="TemplateItemButton">
  <Top>50</Top>
  <Left>1</Left>
  <Width>125</Width>
  <Height>30</Height>
  <AbsoluteLayoutFlags>XProportional</AbsoluteLayoutFlags>
  <Text>Добавить</Text>
  <FontStyle>CollectionSubTitleFont</FontStyle>
  <ForeColor>WhiteSmoke</ForeColor>
  <BackColor>ColorPrimary</BackColor>
  <BorderCorner>7</BorderCorner>
  <Commands>
    <Command Name="MaterialAddValueSetCommand" />
  </Commands>
  <Visible Binding="NotUse" />
</TemplateItem>
```

Создадим команду MaterialAddValueSetCommand типа ValueSetCommand, используемую на кнопке:

{% code title="TemplateMaterialList.xml" %}
```xml
<Command Name="MaterialAddValueSetCommand" Type="ValueSetCommand" Assembly="Commands">
  <DataConnection Name="MaterialConvertDataConnection">
    <Property Name="UpdateRow">
      <Parameters>
        <Parameter Name="RowIndex">
          <DataConnection SourceDataConnection="MaterialConvertDataConnection">
            <Property Name="RowIndexOf">
              <Parameters>
                <Parameter Name="ColumnNames">
                  <Structure Type="List">
                    <Item>MaterialId</Item>
                  </Structure>
                </Parameter>
                <Parameter Name="Values">
                  <Structure Type="List">
                    <Item>
                      <Object Name="MaterialCollectionView">
                        <Property Name="SelectedItemValueByFieldName">
                          <Parameters>
                            <Parameter Name="FieldName">MaterialId</Parameter>
                          </Parameters>
                        </Property>
                      </Object>
                    </Item>
                  </Structure>
                </Parameter>
              </Parameters>
            </Property>
          </DataConnection>
        </Parameter>
        <Parameter Name="ColumnNames">
          <Structure Type="List">
            <Item>NotUse</Item>
            <Item>Selected</Item>
            <Item>Quantity</Item>
            <Item>TotalPrice</Item>
            <Item>Added</Item>
            <Item>Updated</Item>
            <Item>Deleted</Item>
          </Structure>
        </Parameter>
        <Parameter Name="Values">
          <Structure Type="List">
            <Item>False</Item>
            <Item>True</Item>
            <Item>1</Item>
            <Item>
              <Calculate>
                <Expression>{0} * 1</Expression>
                <Items>
                  <Item>
                    <Object Name="MaterialCollectionView">
                      <Property Name="SelectedItemValueByFieldName">
                        <Parameters>
                          <Parameter Name="FieldName">UnitPrice</Parameter>
                        </Parameters>
                      </Property>
                    </Object>
                  </Item>
                </Items>
              </Calculate>
            </Item>
            <Item>
              <Condition Name="SelectedIDIsNullOrEmptyCondition" />
            </Item>
            <Item>
              <Not>
                <Condition Name="SelectedIDIsNullOrEmptyCondition" />
              </Not>
            </Item>
            <Item>False</Item>
          </Structure>
        </Parameter>
      </Parameters>
    </Property>
  </DataConnection>
</Command>
```
{% endcode %}

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

Так же изменяем значения в полях Added, Updated и Deleted. Новые значения для Added и Updated зависят от наличия временного идентификатора на тот случай, если сначала удалили товар, и сразу нажали на кнопку _Добавить._ Если у товара есть временный ID, то мы должны рассматривать изменение существующего, а не добавление нового.

### Управление количеством

Первой опишем кнопку уменьшения количества:

```xml
<ItemElement Type="TemplateItemButton">
  <Top>50</Top>
  <Left>0.72</Left>
  <Width>30</Width>
  <Height>30</Height>
  <AbsoluteLayoutFlags>XProportional</AbsoluteLayoutFlags>
  <BackColor>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>DarkGray70</Then>
      </Case>
      <Case>VeryLightGray</Case>
    </Switch>
  </BackColor>
  <BorderCorner>7</BorderCorner>
  <ImageSource>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>Images\minus-light.png</Then>
      </Case>
      <Case>Images\minus-dark.png</Case>
    </Switch>
  </ImageSource>
  <Commands>
    <If>
      <When>
        <Condition Name="QuantityOfSelectedMaterialGreater1Condition" />
      </When>
      <Then>
        <Command Name="MaterialDecrementQuantityValueSetCommand" />
      </Then>
      <Else>
        <Command Name="MaterialDeleteValueSetCommand" />
      </Else>
    </If>
  </Commands>
  <Visible Binding="Selected" />
</ItemElement>
```

В условие QuantityOfSelectedMaterialGreater1Condition проверяем количество на больше единицы, чтобы определить, какую команду следует выполнить. Если количество больше единицы, то будем его уменьшать на единицу, а если равно единицы, то меняем значения флагов NotUse и Selected на противоположные, а количество сбрасываем на 0.

Самостоятельно напишите условие и обе команды. Не забудьте менять значения в полях Added, Updated и Deleted, учитывая при этом временный ID. Если у товара нет временного идентификатора, то можно просто сбросить количество и не помечать его на удаление из карточки заказа. При уменьшении количества товара важно правильно&#x20;

Текущее количество товара будем отображать в объекте:

```xml
<TemplateItem Type="TemplateItemLabel">
  <Top>50</Top>
  <Left>0.87</Left>
  <Width>45</Width>
  <Height>30</Height>
  <AbsoluteLayoutFlags>XProportional</AbsoluteLayoutFlags>
  <FontStyle>CollectionTitleFont</FontStyle>
  <ForeColor>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>WhiteSmoke</Then>
      </Case>
      <Case>VeryDarkGray</Case>
    </Switch>
  </ForeColor>
  <BorderCorner>7</BorderCorner>
  <BackColor>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>DarkGray70</Then>
      </Case>
      <Case>VeryLightGray</Case>
    </Switch>
  </BackColor>
  <TextAlignment Vertical="Center" Horizontal="Center" />
  <Padding Left="5" Top="0" Right="5" Bottom="0" />
  <Text Binding="Quantity" />
  <Visible Binding="Selected" />
</TemplateItem>
```

Кнопка увеличения количества товара, будет выполнять только одну команду:

```xml
<ItemElement Type="TemplateItemButton">
  <Top>50</Top>
  <Left>0.99</Left>
  <Width>30</Width>
  <Height>30</Height>
  <AbsoluteLayoutFlags>XProportional</AbsoluteLayoutFlags>
  <BackColor>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>DarkGray70</Then>
      </Case>
      <Case>VeryLightGray</Case>
    </Switch>
  </BackColor>
  <BorderCorner>7</BorderCorner>
  <ImageSource>
    <Switch>
      <Case>
        <When>
          <Condition Name="AppThemeDarkEqualCondition" />
        </When>
        <Then>Images\plus-light.png</Then>
      </Case>
      <Case>Images\plus-dark.png</Case>
    </Switch>
  </ImageSource>
  <Commands>
    <Command Name="MaterialIncrementQuantityValueSetCommand" />
  </Commands>
  <Visible Binding="Selected" />
</ItemElement>
```

Самостоятельно создайте команду MaterialIncrementQuantityValueSetCommand.

Добавим в файл формы описание цвета, который используется в тэгах `<BackColor>` созданных элементов:

{% code title="TemplateMaterialList.xml" %}
```xml
<Color Name="DarkGray70" Red="70" Green="70" Blue="70" Alpha="255" />
```
{% endcode %}

Запустим приложение, чтобы проверить отображение и работу новых элементов:



Отлично! Теперь можем реализовать логику передачи данных на родительский экран, где будем обновлять список позиций заказа.

### Передача изменений

В заголовок формы (HeadPanel) добавим кнопку _Сохранить_:

{% code title="TemplateMaterialList.xml" %}
```xml
<MyObject Name="SaveButton" Type="Button" Assembly="BaseControls">
  <Top>0</Top>
  <Right>
    <Calculate>
      <Expression>{0} - 15</Expression>
      <Items>
        <Item>
          <Object Name="HeadPanel">
            <Property Name="Width" />
          </Object>
        </Item>
      </Items>
    </Calculate>
  </Right>
  <Height>
    <Object Name="HeadPanel">
      <Property Name="Height" />
    </Object>
  </Height>
  <Width>100</Width>
  <TextAlign>MiddleCenter</TextAlign>
  <Text>Сохранить</Text>
  <FontStyle>ButtonFont</FontStyle>
  <ForeColor>ColorPrimary</ForeColor>
  <BackColor>
    <Object Name="HeadPanel">
      <Property Name="BackColor" />
    </Object>
  </BackColor>
  <Commands>
    <Command Name="SaveSequentialCommand" />
    <Command Name="FormCloseCommand" />
  </Commands>
</MyObject>
```
{% endcode %}

Создайте самостоятельно команду SaveSequentialCommand типа [SequentialCommand](https://wfsys.gitbook.io/workflow-web-forms-syntax/workflow_webforms/commands/sequential_command), оставив ее пока пустой.

Добавим параметры формы, в которых будем возвращать данные по товарам:

{% code title="TemplateMaterialList.xml" %}
```xml
<Parameter Name="MaterialArrayToAdd" />
<Parameter Name="MaterialArrayToEdit" />
<Parameter Name="MaterialArrayToDelete" />
```
{% endcode %}

Создадим команды на запись данных в параметры.

Первой будет команда для параметра MaterialArrayToAdd. В нем будем получать из MaterialConvertDataConnection все записи, у которых в поле Added стоит значение True:

{% code title="TemplateMaterialList.xml" %}
```xml
<Command Name="MaterialArrayToAddValueSetCommand" Type="ValueSetCommand" Assembly="Commands">
  <Parameter Name="MaterialArrayToAdd">
    <Array>
      <Source>
        <DataConnection SourceDataConnection="MaterialConvertDataConnection">
          <Fields>
            <Field Name="MaterialId" />
            <Field Name="Title" />
            <Field Name="MaterialCategoryTitle" />
            <Field Name="UnitShortTitle" />
            <Field Name="UnitPrice" />
            <Field Name="Quantity" />
            <Field Name="TotalPrice" />
            <Field Name="Added" />
          </Fields>
        </DataConnection>
      </Source>
      <Filter>
        <Index Value="7" />
        <DataType Type="BooleanDataType" />
        <Value>True</Value>
      </Filter>
      <Select>
        <Items>
          <Item Type="Index">0</Item>
          <Item Type="Index">1</Item>
          <Item Type="Index">2</Item>
          <Item Type="Index">3</Item>
          <Item Type="Index">4</Item>
          <Item Type="Index">5</Item>
          <Item Type="Index">6</Item>
        </Items>
      </Select>
    </Array>
  </Parameter>
</Command>
```
{% endcode %}

В параметр MaterialArrayToEdit будем добавлять те записи, у которых в поле Updated стоит значение True и дополнительно будем проверять значение в поле Added, чтобы оно было равно False:

{% code title="TemplateMaterialList.xml" %}
```xml
<Command Name="MaterialArrayToEditValueSetCommand" Type="ValueSetCommand" Assembly="Commands">
  <Parameter Name="MaterialArrayToEdit">
    <Array>
      <Source>
        <DataConnection SourceDataConnection="MaterialConvertDataConnection">
          <Fields>
            <Field Name="ID" />
            <Field Name="MaterialId" />
            <Field Name="Title" />
            <Field Name="MaterialCategoryTitle" />
            <Field Name="UnitShortTitle" />
            <Field Name="UnitPrice" />
            <Field Name="Quantity" />
            <Field Name="TotalPrice" />
            <Field Name="Added" />
            <Field Name="Updated" />
          </Fields>
        </DataConnection>
      </Source>
      <Filter Type="Nested">
        <And>
          <Filter>
            <Index Value="8" />
            <DataType Type="BooleanDataType" />
            <Value>False</Value>
          </Filter>
          <Filter>
            <Index Value="9" />
            <DataType Type="BooleanDataType" />
            <Value>True</Value>
          </Filter>
        </And>
      </Filter>
      <Select>
        <Items>
          <Item Type="Index">0</Item>
          <Item Type="Index">1</Item>
          <Item Type="Index">2</Item>
          <Item Type="Index">3</Item>
          <Item Type="Index">4</Item>
          <Item Type="Index">5</Item>
          <Item Type="Index">6</Item>
          <Item Type="Index">7</Item>
        </Items>
      </Select>
    </Array>
  </Parameter>
</Command>
```
{% endcode %}

В параметре храним все поля выбранных записей, т.к. информация о ТМЦ могла быть изменена в базе данных.

В параметре MaterialArrayToDelete будем передавать массив временных идентификаторов товаром, помеченных на удаление:

{% code title="TemplateMaterialList.xml" %}
```xml
<Command Name="MaterialArrayToDeleteValueSetCommand" Type="ValueSetCommand" Assembly="Commands">
  <Parameter Name="MaterialArrayToDelete">
    <Array>
      <Source>
        <DataConnection SourceDataConnection="MaterialConvertDataConnection">
          <Fields>
            <Field Name="ID" />
            <Field Name="Deleted" />
          </Fields>
        </DataConnection>
      </Source>
      <Filter>
        <Index Value="1" />
        <DataType Type="BooleanDataType" />
        <Value>True</Value>
      </Filter>
      <Select>
        <Items>
          <Item Type="Index">0</Item>
        </Items>
      </Select>
    </Array>
  </Parameter>
</Command>
```
{% endcode %}

В карточке заказа будем определять, какие позиции удалить только на форме, а какие пометить для удаления в базе данных.

Объединим все три команды в ранее созданную команду SaveSequentialCommand:

{% code title="TemplateMaterialList.xml" %}
```xml
<Command Name="SaveSequentialCommand" Type="SequentialCommand" Assembly="Commands">
  <Commands>
    <Command Name="MaterialArrayToAddValueSetCommand" />
    <Command Name="MaterialArrayToEditValueSetCommand" />
    <Command Name="MaterialArrayToDeleteValueSetCommand" />

    <Command Name="UpdatedTrueValueSetCommand" />
  </Commands>
</Command>
```
{% endcode %}

Не забываем про паттерн Updated, чтобы на родительском экране корректно отработал Execution.

### Внесение изменений

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

Первым делом создайте условие MaterialListFormUpdatedTrueEqualCondition для проверки возвращаемого параметра Updated и Execution, который будет выполняться по этому условию.&#x20;

Далее будет описывать команды на внесение изменений в OrderPositionConvertDataConnection и добавлять их в созданный Execution.

Команда на добавление позиций в заказ:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="OrderPositionAddCommand" Type="ValueSetCommand" Assembly="Commands">
  <DataConnection Name="OrderPositionConvertDataConnection">
    <Property Name="AddRows">
      <Parameters>
        <Parameter Name="ColumnNames">
          <Structure Type="List">
            <Item>ID</Item>
            <Item>MaterialId</Item>
            <Item>MaterialTitle</Item>
            <Item>MaterialCategoryTitle</Item>
            <Item>UnitShortTitle</Item>
            <Item>UnitPrice</Item>
            <Item>UnitPriceString</Item>
            <Item>Quantity</Item>
            <Item>TotalPrice</Item>
            <Item>QuantityString</Item>
            <Item>Updated</Item>
            <Item>Deleted</Item>
            <Item>IsNew</Item>
          </Structure>
        </Parameter>
        <Parameter Name="Values">
          <Array>
            <Source>
              <Command Name="MaterialListFormShowCommand" Parameter="MaterialArrayToAdd" />
            </Source>
            <Select>
              <Items>
                <Item Type="Value">
                  <Object Name="CounterVariable" />
                </Item>
                <Item Type="Index">0</Item><!-- MaterialId -->
                <Item Type="Index">1</Item><!-- Title -->
                <Item Type="Index">2</Item><!-- MaterialCategoryTitle -->
                <Item Type="Index">3</Item><!-- UnitShortTitle -->
                <Item Type="Index">4</Item><!-- UnitPrice -->
                <Item Type="Format">{4} руб./{3}</Item><!-- UnitPriceString -->
                <Item Type="Index">5</Item><!-- Quantity -->
                <Item Type="Format">{6} руб.</Item><!--TotalPrice-->
                <Item Type="Format">{5} {3}</Item><!--QuantityString-->
                <Item Type="Value">False</Item>
                <Item Type="Value">False</Item>
                <Item Type="Value">True</Item>
              </Items>
            </Select>
          </Array>
        </Parameter>
      </Parameters>
    </Property>
  </DataConnection>
</Command>
```
{% endcode %}

Здесь разбираем данные из параметра MaterialArrayToAdd с помощью `<Array>` и добавляем новые строки в OrderPositionConvertDataConnection. Новые позиции помечаем в поле IsNew значением True.

Команда на изменение позиций заказа:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="OrderPositionToEditCommand" Type="ValueSetCommand" Assembly="Commands">
  <DataConnection Name="OrderPositionConvertDataConnection">
    <Property Name="UpdateRows">
      <Parameters>
        <Parameter Name="RowIndices">
          <DataConnection SourceDataConnection="OrderPositionConvertDataConnection">
            <Property Name="RowsIndicesOf">
              <Parameters>
                <Parameter Name="ColumnNames">
                  <Structure Type="List">
                    <Item>ID</Item>
                  </Structure>
                </Parameter>
                <Parameter Name="Values">
                  <Structure Type="List">
                    <Item>
                      <Array>
                        <Source>
                          <Command Name="MaterialListFormShowCommand" Parameter="MaterialArrayToEdit" />
                        </Source>
                        <Select>
                          <Items>
                            <Item Type="Index">0</Item><!-- ID -->
                          </Items>
                        </Select>
                      </Array>
                    </Item>
                  </Structure>
                </Parameter>
              </Parameters>
            </Property>
          </DataConnection>
        </Parameter>
        <Parameter Name="ColumnNames">
          <Structure Type="List">
            <Item>ID</Item>
            <Item>MaterialId</Item>
            <Item>MaterialTitle</Item>
            <Item>MaterialCategoryTitle</Item>
            <Item>UnitShortTitle</Item>
            <Item>UnitPrice</Item>
            <Item>UnitPriceString</Item>
            <Item>Quantity</Item>
            <Item>TotalPrice</Item>
            <Item>QuantityString</Item>
            <Item>Updated</Item>
            <Item>Deleted</Item>
          </Structure>
        </Parameter>
        <Parameter Name="Values">
          <Array>
            <Source>
              <Command Name="MaterialListFormShowCommand" Parameter="MaterialArrayToEdit" />
            </Source>
            <Select>
              <Items>
                <Item Type="Index">0</Item><!-- ID -->
                <Item Type="Index">1</Item><!-- MaterialId -->
                <Item Type="Index">2</Item><!-- Title -->
                <Item Type="Index">3</Item><!-- MaterialCategoryTitle -->
                <Item Type="Index">4</Item><!-- UnitShortTitle -->
                <Item Type="Index">5</Item><!-- UnitPrice -->
                <Item Type="Format">{5} руб./{4}</Item><!-- UnitPriceString -->
                <Item Type="Index">6</Item><!-- Quantity -->
                <Item Type="Format">{7} руб.</Item><!--TotalPrice-->
                <Item Type="Format">{6} {4}</Item><!--QuantityString-->
                <Item Type="Value">True</Item>
                <Item Type="Value">False</Item>
              </Items>
            </Select>
          </Array>
        </Parameter>
      </Parameters>
    </Property>
  </DataConnection>
</Command>
```
{% endcode %}

С помощью get-проперти RowsIndicesOf у ConvertDataConnection находим индексы строк, в которых нужно обновить информацию о товарах.

Чтобы при удалении позиций различать позиции сохраненные в базе данных и недавно добавленные в заказ, создадим объект Variable вида:

{% code title="TemplateOrderEdit.xml" %}
```xml
<MyObject Name="MaterialArrayToDeleteVariable" Type="Variable" Assembly="SimpleControls">
  <Value>
    <Array>
      <Source>
        <DataConnection SourceDataConnection="OrderPositionConvertDataConnection">
          <Fields>
            <Field Name="ID" />
            <Field Name="IsNew" />
          </Fields>
        </DataConnection>
      </Source>
      <Select>
        <Items>
          <Item Type="Number" />
          <Item Type="Index">0</Item>
          <Item Type="Index">1</Item>
        </Items>
      </Select>
      <RightJoin>
        <OuterArray>
          <Command Name="MaterialListFormShowCommand" Parameter="MaterialArrayToDelete" />
        </OuterArray>
        <Keys>
          <Inner Index="1" Type="IntegerDataType" />
          <Outer Index="0" Type="IntegerDataType" />
        </Keys>
        <Result>
          <Inner Index="0" /><!-- Number = RowIndex -->
          <Inner Index="2" /><!-- IsNew -->
        </Result>
      </RightJoin>
    </Array>
  </Value>
</MyObject>
```
{% endcode %}

Объединяем два массива по временному идентификатору записей, и через селектор Number получаем индексы строк. Дальше в командах будем проверять значение во втором поле результирующей таблицы и по нему выделять позиции заказа сохраненные в базе данных.

Первом создадим команду для отмечания позиций на удаление из базы данных:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="OrderPositionToDeleteFromDatabaseCommand" Type="ValueSetCommand" Assembly="Commands">
  <DataConnection Name="OrderPositionConvertDataConnection">
    <Property Name="UpdateRows">
      <Parameters>
        <Parameter Name="RowIndices">
          <Array>
            <Source>
              <Object Name="MaterialArrayToDeleteVariable" />
            </Source>
            <Filter>
              <Index Value="1" /><!-- IsNew -->
              <Value>False</Value>
            </Filter>
            <Select>
              <Items>
                <Item Type="Index">0</Item><!-- RowIndex -->
              </Items>
            </Select>
          </Array>
        </Parameter>
        <Parameter Name="ColumnNames">
          <Structure Type="List">
            <Item>TotalPrice</Item>
            <Item>Quantity</Item>
            <Item>Updated</Item>
            <Item>Deleted</Item>
            <Item>IsNew</Item>
          </Structure>
        </Parameter>
        <Parameter Name="Values">
          <Array>
            <Source>
              <Command Name="MaterialListFormShowCommand" Parameter="MaterialArrayToDelete" />
            </Source>
            <Select>
              <Items>
                <Item Type="Value">0</Item>
                <Item Type="Value">0</Item>
                <Item Type="Value">False</Item>
                <Item Type="Value">True</Item>
                <Item Type="Value">False</Item>
              </Items>
            </Select>
          </Array>
        </Parameter>
        <Parameter Name="ReplicateValues">False</Parameter>
      </Parameters>
    </Property>
  </DataConnection>
</Command>
```
{% endcode %}

В поле Deleted ставим значение True - тем самым помечаем для удаления. Дополнительно сбрасываем значения итоговой цены и количества товара в позиции.

Позиций заказа, которые еще не сохраняли в базе данных, удаляем из OrderPositionConvertDataConnection:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="OrderPositionToDeleteValueSetCommand" Type="ValueSetCommand" Assembly="Commands">
  <DataConnection Name="OrderPositionConvertDataConnection">
    <Property Name="DeleteRowsByIndices">
      <Parameters>
        <Parameter Name="Value">
          <Array>
            <Source>
              <Object Name="MaterialArrayToDeleteVariable" />
            </Source>
            <Filter>
              <Index Value="1" /><!-- IsNew -->
              <Value>True</Value>
            </Filter>
            <Select>
              <Items>
                <Item Type="Index">0</Item><!-- RowIndex -->
              </Items>
            </Select>
          </Array>
        </Parameter>
      </Parameters>
    </Property>
  </DataConnection>
</Command>
```
{% endcode %}

Отлично! Добавим Новые команды в Execution:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Execution>
  <ConditionExpression>
    <Condition Name="MaterialListFormUpdatedTrueEqualCondition" />
  </ConditionExpression>
  <Commands>
    <Command Name="OrderPositionToAddCommand" />
    <Command Name="OrderPositionToEditCommand" />
    <Command Name="OrderPositionToDeleteFromDatabaseCommand" />
    <Command Name="OrderPositionToDeleteValueSetCommand" />
  </Commands>
</Execution>
```
{% endcode %}

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

## Удаление позиции заказа <a href="#delete-order-positions" id="delete-order-positions"></a>

Для удаления позиции заказа из списка будем использовать контекстное меню, вызываемое свайпом карточки влево. Направление свайпа и элементы меню настраиваются - поэтому при необходимости можете настроить вызов меню через свайп вправо, или даже реализовать два разных меню на каждое направление свайпа.

### SwipeMenu <a href="#swipe_menu" id="swipe_menu"></a>

Свайп-меню настраивается в тэге `<SwipeMenu>`, определенном в CollectionView. Добавим в описание объекта OrderPositionCollectionView следующий код:

```xml
<SwipeMenu>
  <RightItems>
    <SwipeItem>
      <Text>Удалить</Text>
      <ImageSource>Images\delete.png</ImageSource>
      <BackColor>SoftRed</BackColor>
      <Commands> </Commands>
    </SwipeItem>
  </RightItems>
</SwipeMenu>
```

Тэг `<RightItems>` содержит список элементов меню `<SwipeItem>`, которые будут отображаться справа от карточки при свайпе влево. Если необходимо отображать меню слева от карточки (при свайпе вправо), то используем тэг `<LeftItems>`.

Элементы свайп-меню описываются тегом `<SwipeItem>`, в котором указывается текст надписи, путь до изображения, цвет фона и последовательность команд.

Добавим в файл описание используемого цвета для кнопки удаления:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Color Name="SoftRed" Red="220" Green="90" Blue="90" Alpha="255" />
```
{% endcode %}

Запустим приложение, чтобы проверить отображение свайп-меню:

<div><figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FhxlZFKdUg3XhB26jINDT%2F04_Swipe_Menu_Light_iOS.png?alt=media&#x26;token=5a3fbae3-de6b-4304-8704-677a0fa81145" alt="" width="311"><figcaption></figcaption></figure> <figure><img src="https://936892128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3leufWq98b2vkRUth1Rx%2Fuploads%2FnN4K2cciRmLuHwFIFTpt%2F04_Swipe_Menu_Dark_iOS.png?alt=media&#x26;token=f397aea4-29a1-44e6-a39f-2c7cf1cc04c1" alt="" width="311"><figcaption></figcaption></figure></div>

### Команды удаления <a href="#delete-commands" id="delete-commands"></a>

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

{% code title="TemplateOrderEdit.xml" %}
```xml
<Command Name="OrderPositionDeleteMessageBoxCommand" Type="MessageBoxCommand" Assembly="Commands">
  <Caption>Удаление</Caption>
  <Text>Вы действительно хотите удалить выбранный товар?</Text>
  <Buttons Type="OkCancel" />
</Command>
```
{% endcode %}

Команду OrderPositionDeleteMessageBoxCommand добавим в тэг `<Commands>` для `<SwipeMenu>` списка позиций заказа.&#x20;

Создадим условие проверки, что выбранная запись была недавно добавлена в заказ и еще не сохранена в базе данных:

{% code title="TemplateOrderEdit.xml" %}
```xml
<Condition Name="SelectedOrderPositionIsNewEqualCondition" Type="EqualCondition" Assembly="Conditions">
  <Items>
    <Item>
      <Object Name="OrderPositionCollectionView">
        <Property Name="SelectedItemValueByFieldName">
          <Parameters>
            <Parameter Name="FieldName">IsNew</Parameter>
          </Parameters>
        </Property>
      </Object>
    </Item>
    <Item>True</Item>
  </Items>
</Condition>
```
{% endcode %}

Создайте самостоятельно команду на удаление новой позиции заказа, назвав ее, например  SwipeDeleteValueSetCommand, и команду на удаление из базы данных, например   SwipeDeleteFromDatabaseCommand. Индексы строк, редактируемых в командах, следует получать из OrderPositionConvertDataConnection по значению из поля ID выбранной позиции заказа.

Создадим Execution, который будет отслеживать значение параметра Ok команды OrderPositionDeleteMessageBoxCommand, и в зависимости от условия SelectedOrderPositionIsNewEqualCondition будет вызывать одну из двух созданных выше команд.

Запустим приложение и проверим удаление позиций заказа.

Отлично! На следующем уроке рассмотрим работу с JSON на форме, для удобного сохранения&#x20;

## Итоги <a href="#results" id="results"></a>

На уроке мы рассмотрели  .

## Ответы <a href="#answer" id="answer"></a>

В архиве присутствуют xml-файлы форм для мобильного приложения и серверный xml-файл, также лежит бэкап базы данных и файл с запросами на изменение структуры базы данных - с помощью файлов можете проверить себя.

{% file src="broken-reference" %}

{% hint style="warning" %}
Архив _не содержит_ xml-файлы форм десктопного приложения.
{% endhint %}
