| Предыдущая лекция | Следующая лекция | |
|---|---|---|
| Подсветка элементов по условию. Дополнительные выборки.Массовая смена цены продукции. | Содержание | Вывод списка материалов продукта. CRUD материалов продукта |
Необходимо добавить возможность редактирования данных существующей продукции, а также добавление новой продукции в новом окне - форме для добавления/редактирования продукции.
Переходы на данное окно должны быть реализованы из главной формы списка: для редактирования - при нажатии на конкретный элемент, для добавления - при нажатии кнопки “Добавить продукцию”.
На форме должны быть предусмотрены следующие поля: артикул, наименование, тип продукта (выпадающий список), изображение, количество человек для производства, номер производственного цеха, минимальная стоимость для агента и подробное описание (с возможностью многострочного ввода).
Также необходимо реализовать вывод списка материалов, используемых при производстве продукции, с указанием количества. В список можно добавлять новые позиции и удалять существующие. При добавлении материалы должны выбираться из выпадающего списка с возможностью поиска по наименованию.
При открытии формы для редактирования все поля выбранного объекта должны быть подгружены в соответствующие поля из базы данных, а таблица заполнена актуальными значениями.
Стоимость продукции может включать сотые части, а также не может быть отрицательной. Система должна проверять существование продукта с введенным артикулом и не давать использовать один артикул для нескольких продуктов.
Пользователь может добавить/заменить изображение у продукции.
Для того чтобы администратор случайно не изменял несколько продуктов, предусмотрите невозможность открытия более одного окна редактирования.
В окне редактирования продукта должна присутствовать кнопка “Удалить”, которая удаляет продукт из базы данных. При этом должны соблюдаться следующие условия. Если у продукта есть информация о материалах, используемых при его производстве, или история изменения цен, то эта информация должна быть удалена вместе с продуктом. Но если у продукта есть информация о его продажах агентами, то удаление продукта из базы данных должно быть запрещено. После удаления продукта система должна сразу вернуть пользователя обратно к списку продукции.
После редактирования/добавления/удаления продукции данные в окне списка продукции должны быть обновлены.
| Критерий | Баллы |
|---|---|
| Реализован переход на окно добавления | 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)
Создайте новое окно: EditProductWindow (в папке Windows - не забываем про логическую структуру проекта)
В классе окна EditProductWindow добавьте свойство currentProduct, в котором будет храниться добавляемый/редактируемый экземпляр продукции:
public Product currentProduct { get; set; }
В разметке окна вставьте аттрибут Name
<Window
...
Name="root">
В конструктор окна добавьте параметр типа Product, присвойте его ранее объявленному свойству. Задайте заголовок окна:
public EditProductWindow(Product editProduct)
{
InitializeComponent();
DataContext = this;
currentProduct = editProduct;
root.Title = currentProduct.ID == 0 ? "Новый продукт" : "Редактирование продукта";
}
В разметке окна редактирования продукции создайте сетку из трёх колонок: в первой у нас будет изображение, во второй редактируемые поля продукта, а в третей список материалов
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
Во вторую колонку добавьте StackPanel с границами (чтобы визуальные компоненты не прилипали к границам окна) и в этом списке разместите редактируемые элементы
На форме должны быть предусмотрены следующие поля: артикул, наименование, тип продукта (выпадающий список), изображение, количество человек для производства, номер производственного цеха, минимальная стоимость для агента и подробное описание
<StackPanel
Grid.Column="1"
Margin="5">
<Label Content="Артикул"/>
<TextBox
Text="{Binding currentProduct.ArticleNumber}"/>
<Label Content="Наименование продукта"/>
<TextBox Text="{Binding currentProduct.Title}"/>
...
</StackPanel>
Обычные поля (числовые и строковые) наклепайте по шаблону сами, а я подробнее остановлюсь на полях: тип продукта, изображение и описание:
Выбор типа продукта из списка
В классе окна объявляем свойство productTypeList - список типов продукции
public List<ProductType> productTypeList { get; set; }
И в конструкторе получаем его из БД:
productTypeList = Globals.dataProvider.getProductTypes().ToList();
В вёрстке окна редактирования продукции мы можем использовать выпадающий список, атрибут SelectedIndex которого позволяет отобразить текущее значение редактируемого элемента
<ComboBox
ItemsSource="{Binding productTypeList}"
SelectedIndex="{Binding selectedProductIndex}"/>
Чтобы получить индекс (позицию в списке) текущего продукта нужно после получения списка типов продуктов добавить поиск:
// в классе окна
public int selectedProductIndex { get; set; } = -1;
...
// в конструкторе окна
if (currentProduct.ID > 0) {
selectedProductIndex = productTypeList.FindIndex(pt => pt.ID == currentProduct.ProductTypeID);
}
смена изображения продукции
Вывод изображения производится как и в главном окне
<Image
Name="CurrentProductImage"
Width="200"
Height="200"
Source="{Binding currentProduct.ImageUri}" />
А для смены изображения используем стандартный диалог открытия файлов, повесив его на кнопку Сменить картинку (кнопку добавьте сами в центральную колонку)
Обработчик кнопки:
private void ChangeImage_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog GetImageDialog = new OpenFileDialog();
// задаем фильтр для выбираемых файлов
// до символа "|" идет произвольный текст, а после него шаблоны файлов разделенные точкой с запятой
GetImageDialog.Filter = "Файлы изображений: (*.png, *.jpg)|*.png;*.jpg";
// чтобы не искать по всему диску задаем начальный каталог
GetImageDialog.InitialDirectory = Environment.CurrentDirectory;
if (GetImageDialog.ShowDialog() == true)
{
// перед присвоением пути к картинке обрезаем начало строки, т.к. диалог возвращает полный путь
currentProduct.Image = GetImageDialog.FileName.Substring(Environment.CurrentDirectory.Length);
// обратите внимание, это другое окно и другой Invalidate, который реализуйте сами
Invalidate();
}
}
Многострочное описание
Тут просто - разрешаем переносы и задаем высоту элемента
<Label Content="Описание продукта"/>
<TextBox
AcceptsReturn="True"
Height="200"
Text="{Binding currentProduct.Description}"/>
Сохранение введенных данных
В разметку добавьте кнопку Сохранить и напишите обработчик
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
// перед сохранением мы должны выполнить несколько проверок, поэтому заворачиваем в исключение
try
{
// могли изменить тип продукта - сохраняем ID
if (ProductTypeComboBox.SelectedItem != null)
{
currentProduct.ProductTypeID = ((ProductType)ProductTypeComboBox.SelectedItem).ID;
} else
{
throw new Exception("Не выбран тип продукта");
}
// TODO проверить стоимость продукции (не более двух знаков после запятой и положительное число)
// TODO проверка артикула (найти в базе запись с таким же артикулом и отличающимся ID)
Globals.dataProvider.saveProduct(currentProduct);
DialogResult = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Реализация метода saveProduct
public void saveProduct(Product product)
{
using (MySqlConnection db = new MySqlConnection(connectionString))
{
if (product.ID == 0)
{
// TODO новый продукт
}
else
{
// изменение существующего
db.Execute("UPDATE Product SET Title=@Title, ProductTypeID=@ProductTypeID, " +
"ArticleNumber=@ArticleNumber, Description=@Description, " +
"Image=@Image, ProductionPersonCount=@ProductionPersonCount, " +
"ProductionWorkshopNumber=@ProductionWorkshopNumber, " +
"MinCostForAgent=@MinCostForAgent " +
"WHERE ID=@ID", product);
}
}
}
для редактирования существующей продукции в списке продукции реализуем обработчик двойного клика
private void ProductListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var product = (sender as ListBox).SelectedItem as Product;
// в создаваемое окно передаем выбранный продукт
var newEditWindow = new EditProductWindow(product);
if ((bool)newEditWindow.ShowDialog())
{
Invalidate();
}
}
для создания нового продукта в разметке главного окна создайте кнопку "Добавить продукцию" (в левой или верхней панели) и в её обработчике создайте новый экземпляр продукта, а дальше то же, что и в предыдущем пункте
var newEditWindow = new EditProductWindow(new Product());
...
В окне редактирования продукта должна присутствовать кнопка “Удалить”, которая удаляет продукт из базы данных. При этом должны соблюдаться следующие условия. Если у продукта есть информация о материалах, используемых при его производстве, или история изменения цен, то эта информация должна быть удалена вместе с продуктом. Но если у продукта есть информация о его продажах агентами, то удаление продукта из базы данных должно быть запрещено. После удаления продукта система должна сразу вернуть пользователя обратно к списку продукции.
Добавьте кнопку Удалить в среднюю колоку (рядом с кнопкой сохранить). Атрибут Visible привяжите к ID продукта (т.е. у нового продукта кнопки удалить быть не должно). Можно реализовать через Binding, но можно задать в конструкторе
И реализуйте обработчик клика по этой кнопке
private void DeleteProductButton_Click(object sender, RoutedEventArgs e)
{
using (var context = new esmirnovContext())
{
try
{
// проверки, требуемые по ТЗ
// TODO исключение, если есть продажи
var saleCount = Globals.dataProvider.saleCount(currentProduct.ID);
if (saleCount > 0)
throw new Exception("Нельзя удалять продукт с продажами");
// TODO удаление списка материалов продукта
Globals.dataProvider.removeProductMaterial(currentProduct.ID);
// TODO удаление истории изменения цен (если есть)
// TODO удаление продукта
Globals.dataProvider.removeProduct(currentProduct.ID);
DialogResult = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Задание
Самостоятельно реализовать код помеченный комментарием TODO
| Предыдущая лекция | Следующая лекция | |
|---|---|---|
| Подсветка элементов по условию. Дополнительные выборки.Массовая смена цены продукции. | Содержание | Вывод списка материалов продукта. CRUD материалов продукта |