| Пагинация, сортировка, фильтрация, поиск | Содержание | Создание, изменение продукции |
| Критерий | Баллы |
|---|---|
| Реализована возможность выделения сразу нескольких элементов в списке | 0.2 |
| После выделения элементов в списке появляется кнопка "Изменить стоимость на ..." | 0.3 |
| При нажатии на кнопку отображается модальное окно для изменения цены | 0.1 |
| В модальном окне есть возможность ввода числового значения | 0.1 |
| По умолчанию введено значение средней цены выбранных продуктов | 0.2 |
| Реализована проверка на ввод только числового значения | 0.2 |
| После нажатия кнопки "Изменить" стоимость всех выбранных продуктов изменяется в БД | 0.5 |
| После нажатия кнопки "Изменить" стоимость всех выбранных продуктов обновляется в списке | 0.2 |
| Итого | 1.8 |
Возможность выделения нескольких элементов в ListView есть, специально её реаизовывать не надо. Надо лишь поймать это событие и сосчитать количество выделенных элементов.
В ListView нужно добавить название (мы потом будем по нему искать количество выделенных элементов) и обработчик события SelectionChanged
x:Name="ProductListView"
SelectionChanged="ListView_SelectionChanged"
Реализуем обработчик ListView_SelectionChanged:
public int ProductsSelectedCount = 0;
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ProductsSelectedCount = ProductListView.SelectedItems.Count;
}
Сначала просто добавляем эту кнопку в разметку
<Button
x:Name="CostChangeButton"
Visibility=""
Content="Изменить стоимость на..."
/>
И запоминаем какие значения может прнимать атрибут Visibility
Теперь, чтобы видимость кнопки зависела от количества выделенных элементов, мы привязываем атрибут Visibility к свойству CostChangeButtonVisible
<Button
x:Name="CostChangeButton"
Visibility="{Binding CostChangeButtonVisible}"
Content="Изменить стоимость на..."
/>
И реализуем это свойство в коде ОКНА
public string CostChangeButtonVisible {
get {
if (ProductsSelectedCount > 1) return "Visible";
return "Collapsed";
}
}
Осталось в обработчик события ListView_SelectionChanged вставить вызов метода PropertyChanged для свойства CostChangeButtonVisible
Чтобы не плодить кучу одинаковых методов, я добавил в параметры метода Invalidate имя свойства, которое изменилось
private void Invalidate(string ComponentName = "ProductList") {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(ComponentName));
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ProductsSelectedCount = ProductListView.SelectedItems.Count;
Invalidate("CostChangeButtonVisible");
}
Добавляем кнопке обработчик события клика
<Button
x:Name="CostChangeButton"
Visibility="{Binding CostChangeButtonVisible}"
Click="CostChangeButton_Click"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Content="Изменить стоимость на..."
/>
Создаем и показываем модальное окно
Во-первых, вспоминаем, что мы должны соблюдать файловую структуру проекта, т.е. все однотипные объекты распихивать по соответствующим папкам.
Создадим папку Windows и в неё добавим окно (WPF)
Название окна должно быть осмысленным и с суффиксом Window. У меня получилось EnterMinCostForAgentWindow
Можно в каталог
Windowsперетащить и главное окно MainWindow. Только в этом случае надо в разметке приложения (App.xaml) добавить название каталога:><Application x:Class="mysql.App" > xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" > xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > xmlns:local="clr-namespace:mysql" > StartupUri="Windows/MainWindow.xaml"> > ^^^^^^^^ >... Опять же, все окна должны иметь нормальные заголовки. В разметке окна поменяйте атрибут *Title* элемента **Window** (это надо сделать и для основного окна) Содержимое у этого окна элементарное (текстовое поле и кнопка):xml
<StackPanel Orientation="Vertical" Margin="0,50,0,0"><TextBox Name="CostTextBox" /> <Button Content="Изменить"/> </StackPanel>
В коде этого окна меняем конструктор:
cs public EnterMinCostForAgentWindow(decimal AvgCost)
^^^^^^^^^^^^^^^
{
InitializeComponent();
CostTextBox.Text = AvgCost.ToString();
} ```
Во-первых, в конструктор добавляем параметр (средняя цена). Во-вторых, записываем эту цену в текстовое поле.
По условиям задачи мы должны вычислить среднюю цену для выделенных элементов списка (я на вскидку не нашёл как преобразовать IList в IEnumerable, поэтому тупо перебираем список выбранных элементов, считаем сумму и, заодно, собираем список идентификаторов)
private void CostChangeButton_Click(object sender, RoutedEventArgs e)
{
decimal Sum = 0;
List<int> idList = new List<int>();
foreach (Product item in ProductListView.SelectedItems){
Sum += item.MinCostForAgent;
idList.Add(item.ID);
}
// создаём окно, передавая ему среднюю цену
var NewWindow = new EnterMinCostForAgentWindow(
AvgSum / ProductListView.SelectedItems.Count);
// показываем МОДАЛЬНОЕ окно
NewWindow.ShowDialog();
}
Проверка на ввод только числового значения.
private void Button_Click(object sender, RoutedEventArgs e)
{
try
{
// пробуем сконвертировать в число
Result = Convert.ToDecimal(CostTextBox.Text);
// при присвоении результата свойству DialogResult модальное окно закрывается
DialogResult = true;
}
catch (Exception)
{
MessageBox.Show("Стоимость должна быть числом");
}
}
Запись новой цены в БД и обновление списка.
редактируем пункт 3, добавляя анализ результата
if((bool)NewWindow.ShowDialog())
{
// вся работа с БД у нас в DataProvider-e,
// передаем список идентификаторов и новую цену
Globals.DataProvider.SetAverageCostForAgent(idList, NewWindow.Result);
// для перерисовки списка продукции просто перечитываем его
ProductList = Globals.DataProvider.GetProducts();
}
Описываем метод SetAverageCostForAgent в интерфейсе IDataProvider:
void SetAverageCostForAgent(List<int> ProductIds, decimal NewCost);
И реализуем его в MySQLDataProvider-e:
public void SetAverageCostForAgent(List<int> ProductIds, decimal NewCost)
{
try
{
Connection.Open();
try
{
// вместо значений записываем шаблоны
string Query = @"UPDATE
Product
SET MinCostForAgent=@MinCostForAgent
WHERE ID=@ID";
// перебираем список идентификаторов
foreach (int item in ProductIds)
{
MySqlCommand Command = new MySqlCommand(Query, Connection);
// заменяем шаблоны параметрами
Command.Parameters.AddWithValue("@MinCostForAgent", NewCost);
Command.Parameters.AddWithValue("@ID", item);
// и выполняем запрос
Command.ExecuteNonQuery();
}
}
finally
{
Connection.Close();
}
}
catch (Exception)
{
}
}
| Пагинация, сортировка, фильтрация, поиск | Содержание | Создание, изменение продукции |