Преглед изворни кода

пагинатор списком

Евгений Колесников пре 3 година
родитељ
комит
fb61ce16bb
2 измењених фајлова са 101 додато и 57 уклоњено
  1. 29 56
      articles/cs_coloring2.md
  2. 72 1
      articles/cs_pagination2.md

+ 29 - 56
articles/cs_coloring2.md

@@ -1,5 +1,5 @@
 <table style="width: 100%;"><tr><td style="width: 40%;">
 <table style="width: 100%;"><tr><td style="width: 40%;">
-<a href="../articles/cs_pagination.md">Пагинация, сортировка, фильтрация, поиск
+<a href="../articles/cs_pagination2.md">Пагинация, сортировка, фильтрация, поиск
 </a></td><td style="width: 20%;">
 </a></td><td style="width: 20%;">
 <a href="../readme.md">Содержание
 <a href="../readme.md">Содержание
 </a></td><td style="width: 40%;">
 </a></td><td style="width: 40%;">
@@ -124,7 +124,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 
 ## Отображение кнопки "Изменить стоимость на ..."
 ## Отображение кнопки "Изменить стоимость на ..."
 
 
-Сначала просто добавляем эту кнопку в разметку
+Сначала просто добавляем эту кнопку в разметку (можно в панель управления, можно в левую панель)
 
 
 ```xml
 ```xml
 <Button
 <Button
@@ -196,7 +196,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 
 2. Создаем и показываем модальное окно
 2. Создаем и показываем модальное окно
 
 
-    Во-первых, вспоминаем, что мы должны соблюдать файловую структуру проекта, т.е. все однотипные объекты распихивать по соответствующим папкам. 
+    >Вспоминаем, что мы должны соблюдать файловую структуру проекта, т.е. все однотипные объекты распихивать по соответствующим папкам. 
     
     
     Создадим папку `Windows` и в неё добавим окно (WPF)
     Создадим папку `Windows` и в неё добавим окно (WPF)
 
 
@@ -244,7 +244,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
     }
     }
     ```
     ```
 
 
-    Во-первых, в конструктор добавляем параметр (средняя цена). Во-вторых, записываем эту цену в текстовое поле.
+    **Во-первых**, в конструктор добавляем параметр (средняя цена). **Во-вторых**, записываем эту цену в текстовое поле.
 
 
 3. По условиям задачи мы должны вычислить среднюю цену для выделенных элементов списка (я на вскидку не нашёл как преобразовать **IList** в **IEnumerable**, поэтому тупо перебираем список выбранных элементов, считаем сумму и, заодно, собираем список идентификаторов)
 3. По условиям задачи мы должны вычислить среднюю цену для выделенных элементов списка (я на вскидку не нашёл как преобразовать **IList** в **IEnumerable**, поэтому тупо перебираем список выбранных элементов, считаем сумму и, заодно, собираем список идентификаторов)
 
 
@@ -260,7 +260,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 
         // создаём окно, передавая ему среднюю цену    
         // создаём окно, передавая ему среднюю цену    
         var NewWindow = new EnterMinCostForAgentWindow(
         var NewWindow = new EnterMinCostForAgentWindow(
-            AvgSum / ProductListView.SelectedItems.Count);
+            Sum / ProductListView.SelectedItems.Count);
 
 
         // показываем МОДАЛЬНОЕ окно    
         // показываем МОДАЛЬНОЕ окно    
         NewWindow.ShowDialog();
         NewWindow.ShowDialog();
@@ -291,64 +291,37 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 
 5. Запись новой цены в БД и обновление списка.
 5. Запись новой цены в БД и обновление списка.
 
 
-    * редактируем пункт 3, добавляя анализ результата
+Редактируем пункт 3, добавляя анализ результата модального окна
 
 
-        ```cs
-        if((bool)NewWindow.ShowDialog())
+```cs
+if ((bool)NewWindow.ShowDialog())
+{
+    using (var context = new ksmirnovContext())
+    {
+        // выбираем выделенные продукты из БД
+        var query = context.Products.Where(
+            p => idList.Contains(p.Id));
+
+        // меняем им стоимость
+        foreach (var product in query)
         {
         {
-            // вся работа с БД у нас в DataProvider-e, 
-            // передаем список идентификаторов и новую цену
-            Globals.DataProvider.SetAverageCostForAgent(idList, NewWindow.Result);
-            // для перерисовки списка продукции просто перечитываем его
-            ProductList = Globals.DataProvider.GetProducts();
+            product.MinCostForAgent = NewWindow.Result;
         }
         }
-        ```
-
-    * Описываем метод *SetAverageCostForAgent* в интерфейсе **IDataProvider**:
 
 
-        ```cs
-        void SetAverageCostForAgent(List<int> ProductIds, decimal NewCost);
-        ```
+        // сохраняем данные
+        context.SaveChanges();
 
 
-    * И реализуем его в **MySQLDataProvider**-e:
+        // перечитываем список продукции
+        ProductList = context.Products
+            .Include(product => product.ProductType)
+            .Include(product => product.ProductMaterials)
+            .ToList();
+    }
+}
+```
 
 
-        ```cs
-        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)
-            {
-            }
-        }
-        ```
 <table style="width: 100%;"><tr><td style="width: 40%;">
 <table style="width: 100%;"><tr><td style="width: 40%;">
-<a href="../articles/cs_pagination.md">Пагинация, сортировка, фильтрация, поиск
+<a href="../articles/cs_pagination2.md">Пагинация, сортировка, фильтрация, поиск
 </a></td><td style="width: 20%;">
 </a></td><td style="width: 20%;">
 <a href="../readme.md">Содержание
 <a href="../readme.md">Содержание
 </a></td><td style="width: 40%;">
 </a></td><td style="width: 40%;">

+ 72 - 1
articles/cs_pagination2.md

@@ -8,6 +8,8 @@
 
 
 Продолжаем реализовывать макет
 Продолжаем реализовывать макет
 
 
+>Нужно вспомнить материалы прошлогодних лекций про [INotifyPropertyChanged](https://github.com/kolei/OAP/blob/master/articles/wpf_filtering.md)
+
 * [Пагинация](#пагинация)
 * [Пагинация](#пагинация)
 * [Сортировка](#сортировка)
 * [Сортировка](#сортировка)
 * [Фильтрация](#фильтрация)
 * [Фильтрация](#фильтрация)
@@ -66,7 +68,13 @@ public IEnumerable<Product> productList {
 
 
 ## Динамический вывод номеров страниц 
 ## Динамический вывод номеров страниц 
 
 
-В принципе можно руками в разметке нарисовать эти элементы, и может даже эксперты не обратят на это внимания. Но рассмотрим всё-таки правильный вариант.
+В принципе можно руками в разметке нарисовать эти элементы, и может даже эксперты не обратят на это внимания. Но рассмотрим всё-таки ~~правильный вариант~~. 
+
+Этот вариант рабочий, но проще сделать по [другому](#пагинация-версия-2)
+
+<details>
+
+<summary>Вариант пагинатора с программным созданием элементов</summary>
 
 
 1. В разметку страницы под **ListView** добавьте **пустой** именованный **StackPanel** (горизонтальный с выравниванием по правому краю)
 1. В разметку страницы под **ListView** добавьте **пустой** именованный **StackPanel** (горизонтальный с выравниванием по правому краю)
 
 
@@ -136,6 +144,7 @@ public IEnumerable<Product> productList {
         }   
         }   
     }
     }
     ```
     ```
+</details>
 
 
 # Сортировка
 # Сортировка
 
 
@@ -404,6 +413,68 @@ public IEnumerable<Product> ProductList {
 }
 }
 ```
 ```
 
 
+# Пагинация (версия 2)
+
+Пагинацию можно сделать проще:
+
+1. В вёрстке использовать горизонтальный **ListView** (есть в прошлой версии про вёрстку плиткой)
+
+    Вместо `<StackPanel Name="Paginator"...`
+
+    ```xml
+    <ListView
+        ItemsSource="{Binding PageList}"
+        Grid.Column="1"
+        Grid.Row="2">
+
+        <ListView.ItemsPanel>
+            <ItemsPanelTemplate>
+                <WrapPanel 
+                    HorizontalAlignment="Right" />
+            </ItemsPanelTemplate>
+        </ListView.ItemsPanel>
+
+        <ListView.ItemTemplate>
+            <DataTemplate>
+                <TextBlock 
+                    Margin="5"
+                    Text="{Binding label}" 
+                    PreviewMouseDown="TextBlock_PreviewMouseDown"/>
+            </DataTemplate>
+        </ListView.ItemTemplate>
+    </ListView>
+    ```
+
+2. В проект добавить класс **PageItem**
+
+    ```cs
+    public class PageItem
+    {
+        public string label { get; set; }
+    }
+    ```
+
+3. В классе окна объявить переменную **PageList** и в геттере списка продукции заполнять её, а не генерировать динамически содержимое для пагинатора
+
+    ```cs
+    public List<PageItem> PageList { get; set; } = new List<PageItem>();
+
+    ...
+
+    // в геттере
+    PageList.Clear();
+    PageList.Add(new PageItem { label = "<" });
+    for (int i = 1; i <= (Result.Count() / 20) + 1; i++){
+        PageList.Add(new PageItem { label = i.ToString() });
+    }
+    PageList.Add(new PageItem { label = ">" });
+
+    // не забываем уведомить визуальный интерфейс о том, что список страниц изменился
+    Invalidate("PageList");
+    ```
+
+---
+
 <table style="width: 100%;"><tr><td style="width: 40%;">
 <table style="width: 100%;"><tr><td style="width: 40%;">
 <a href="../articles/cs_layout2.md">Вывод данных согласно макету (ListView, Image)
 <a href="../articles/cs_layout2.md">Вывод данных согласно макету (ListView, Image)
 </a></td><td style="width: 20%;">
 </a></td><td style="width: 20%;">