Предыдущая лекция | | Следующая лекция :----------------:|:----------:|:----------------: [Подсветка элементов по условию. Дополнительные выборки.Массовая смена цены продукции.](./cs_pagination2.md) | [Содержание](../readme.md#c-и-mysql) | [Вывод списка материалов продукта. CRUD материалов продукта](./cs_product_material.md) # Добавление/редактирование продукции * [Создание окна редактирования продукции](#создание-окна-редактирования-продукции) * [Открытие окна редактирования для существующей и новой продукции](#открытие-окна-редактирования-для-существующей-и-новой-продукции) * [Проверки перед сохранением продукта](#проверки-перед-сохранением-продукта) * [Удаление продукции](#удаление-продукции) >Необходимо добавить возможность редактирования данных существующей продукции, а также добавление новой продукции в новом окне - форме для добавления/редактирования продукции. > >Переходы на данное окно должны быть реализованы из главной формы списка: для редактирования - при нажатии на конкретный элемент, для добавления - при нажатии кнопки “Добавить продукцию”. > >На форме должны быть предусмотрены следующие поля: артикул, наименование, тип продукта (выпадающий список), изображение, количество человек для производства, номер производственного цеха, минимальная стоимость для агента и подробное описание (с возможностью многострочного ввода). > >Также необходимо реализовать вывод списка материалов, используемых при производстве продукции, с указанием количества. В список можно добавлять новые позиции и удалять существующие. При добавлении материалы должны выбираться из выпадающего списка с возможностью поиска по наименованию. > >При открытии формы для редактирования все поля выбранного объекта должны быть подгружены в соответствующие поля из базы данных, а таблица заполнена актуальными значениями. > >Стоимость продукции может включать сотые части, а также не может быть отрицательной. Система должна проверять существование продукта с введенным артикулом и не давать использовать один артикул для нескольких продуктов. > >Пользователь может добавить/заменить изображение у продукции. > >Для того чтобы администратор случайно не изменял несколько продуктов, предусмотрите невозможность открытия более одного окна редактирования. > >В окне редактирования продукта должна присутствовать кнопка “Удалить”, которая удаляет продукт из базы данных. При этом должны соблюдаться следующие условия. Если у продукта есть информация о материалах, используемых при его производстве, или история изменения цен, то эта информация должна быть удалена вместе с продуктом. Но если у продукта есть информация о его продажах агентами, то удаление продукта из базы данных должно быть запрещено. После удаления продукта система должна сразу вернуть пользователя обратно к списку продукции. > >После редактирования/добавления/удаления продукции данные в окне списка продукции должны быть обновлены. Критерий | Баллы ---------|:---: Реализован переход на окно добавления | 0.1 Реализован переход на окно редактирования выбранного объекта | 0.2 Присутствуют все поля для заполнения | 0.5 При редактировании продукции в поля для ввода загружены данные из БД | 0.3 Выбор типа продукта реализован в виде выпадающего списка со значениями из БД | 0.3 Для ввода описания продукции предусмотрено многострочное поле для ввода | 0.2 ***Реализован список используемых материалов для текущего продукта*** | 0.3 ***В списке присутствует название материала и используемое количество*** | 0.2 ***При редактировании продукции список материалов заполнен значениями из БД*** | 0.2 ***В список можно добавлять новые позиции*** | 0.3 ***Из списка можно удалять существующие позиции*** | 0.2 ***При добавлении материалы выбираются из выпадающего списка со значениями из БД*** | 0.3 ***В списке материалов реализована возможность поиска по наименованию*** | 0.2 ***Список используемых материалов сохраняется в БД при добавлении*** | 0.5 ***Список используемых материалов сохраняется в БД при редактировании*** | 0.5 Стоимость продукции не может быть отрицательной | 0.1 Стоимость продукции записывается только с точностью до сотых | 0.2 Реализована проверка артикула на уникальность | 0.3 Есть возможность выбрать изображение | 0.2 Изображение продукции подгружается из БД при редактировании | 0.2 Есть возможность заменить изображение | 0.1 Данные при добавлении сохраняются в БД | 0.5 Данные при редактировании изменяются в БД | 0.5 Открывается только одно окно редактирования | 0.1 *Реализовано удаление выбранного продукта, у которого не заполнен список используемых материалов* | 0.2 *Реализовано удаление продукта вместе с информацией об используемых материалах* | 0.5 *Запрещено удаление продукта, по которому были выполнены продажи агентом* | 0.3 *После удаления реализован автоматический переход обратно в список* | 0.1 После закрытия окна данные в таблице обновляются | 0.3 **Итого** | **7.9** ## Создание окна редактирования продукции Для добавления и редактирования мы будем использовать одно и то же окно. Заголовок окна будем вычислять по наличию ID у продукции (у новой записи это поле равно `0`) 1. Создайте новое окно: **EditProductWindow** (в папке **Windows** - не забываем про логическую структуру проекта) 1. В классе окна **EditProductWindow** добавьте **свойство** *currentProduct*, в котором будет храниться добавляемый/редактируемый экземпляр продукции: ```cs public Product currentProduct { get; set; }; ``` 1. В разметке окна вставьте аттрибут *Name* ```xml ``` 1. В конструктор окна добавьте параметр типа **Product**, присвойте его ранее объявленному свойству. Задайте заголовок окна: ```cs public EditWindow(Product EditProduct) { currentProduct = editProduct; InitializeComponent(); root.Title = currentProduct.Id == 0 ? "Новый продукт" : "Редактирование продукта"; } ``` 1. В разметке окна редактирования продукции создайте сетку из трёх колонок: в первой у нас будет изображение, во второй редактируемые поля продукта, а в третей список материалов ```xml ``` 1. Во вторую колонку добавьте **StackPanel** с границами (чтобы визуальные компоненты не прилипали к границам окна) и в этом списке разместите редактируемые элементы >На форме должны быть предусмотрены следующие поля: _артикул_, _наименование_, _тип продукта_ (выпадающий список), _изображение_, _количество человек для производства_, _номер производственного цеха_, _минимальная стоимость для агента_ и _подробное описание_ ```xml ``` Обычные поля наклепайте по шаблону сами, а я подробнее остановлюсь на полях: *тип продукта*, *изображение* и *описание*: * Выбор типа продукта из списка В классе окна объявляем свойство *productTypeList* - список типов продукции ```cs public IEnumerable productTypeList { get; set; } ``` И в конструкторе получаем его из БД: ```cs using (var context = new ksmirnovContext()) { productTypeList = context.ProductTypes.ToList(); } ``` В вёрстке окна редактирования продукции мы можем использовать выпадающий список, атрибут *SelectedItem* которого позволяет отобразить **текущее** значение редактируемого элемента ```xml ``` >Из документации: *Класс ComboBox выполняет поиск указанного объекта с помощью **IndexOf** метода. Этот метод, в свою очередь, использует метод **Equals** для определения равенства (объектов)*. А метод **Equals** сравнивает объекты по уникальному идентификатору (встроенное свойство у базового класса в C#, не путать с полем `id` таблицы БД), т.е. свойство **ProductType** у экземпляра продукции **НЕ РАВНО** экземпляру элемента списка *productTypeList* Чтобы исправить эту неприятность нужно переопределить метод **Equals** у класса **ProductType**: ```cs public override bool Equals(object obj) { return (obj != null) && (obj is ProductType) && (this.Id == (obj as ProductType).Id); } ``` Здесь мы проверяем определён ли вообще объект (у нового продукта его ещё нет), нужного ли он типа и совпадет ли его **Id** с **Id** текущего типа продукции * смена изображения продукции Вывод изображения производится как и в главном окне ```xml ``` А для смены изображения используем стандартный диалог открытия файлов, повесив его на кнопку *Сменить картинку* (кнопку добавьте сами в центральную колонку) Обработчик кнопки: ```cs private void ChangeImage_Click(object sender, RoutedEventArgs e) { var getImageDialog = new OpenFileDialog(); // задаем фильтр для выбираемых файлов getImageDialog.Filters.Add( new FileDialogFilter() { Name = "Файлы изображений", Extensions = {"png", "jpg", "jpeg"}}); // чтобы не искать по всему диску задаем начальный каталог // В ТЕКУЩЕЙ ВЕРСИИ АВАЛОНИИ ТАКОГО СВОЙСТВА НЕТ // getImageDialog.InitialDirectory = Environment.CurrentDirectory; // открываем СИНХРОННО диалог // в ответ получим массив выбранных файлов var files = await getImageDialog.ShowAsync(this); if (files != null) { // перед присвоением пути к картинке обрезаем начало строки, т.к. диалог возвращает полный путь currentProduct.Image = files[0].Substring(Environment.CurrentDirectory.Length); // тут нужно либо реализовать интерфейс InotifyPropertyChanged // и обновить информацию о картинке // либо тупо поменять свойство нужного контрола CurrentProductImage.Source = currentProduct.ImageBitmap; } } ``` * Многострочное описание Тут просто - разрешаем переносы и задаем высоту элемента ```xml