Pārlūkot izejas kodu

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

Евгений Колесников 3 gadi atpakaļ
vecāks
revīzija
fb61ce16bb
2 mainītis faili ar 101 papildinājumiem un 57 dzēšanām
  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%;">
-<a href="../articles/cs_pagination.md">Пагинация, сортировка, фильтрация, поиск
+<a href="../articles/cs_pagination2.md">Пагинация, сортировка, фильтрация, поиск
 </a></td><td style="width: 20%;">
 <a href="../readme.md">Содержание
 </a></td><td style="width: 40%;">
@@ -124,7 +124,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 ## Отображение кнопки "Изменить стоимость на ..."
 
-Сначала просто добавляем эту кнопку в разметку
+Сначала просто добавляем эту кнопку в разметку (можно в панель управления, можно в левую панель)
 
 ```xml
 <Button
@@ -196,7 +196,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 2. Создаем и показываем модальное окно
 
-    Во-первых, вспоминаем, что мы должны соблюдать файловую структуру проекта, т.е. все однотипные объекты распихивать по соответствующим папкам. 
+    >Вспоминаем, что мы должны соблюдать файловую структуру проекта, т.е. все однотипные объекты распихивать по соответствующим папкам. 
     
     Создадим папку `Windows` и в неё добавим окно (WPF)
 
@@ -244,7 +244,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
     }
     ```
 
-    Во-первых, в конструктор добавляем параметр (средняя цена). Во-вторых, записываем эту цену в текстовое поле.
+    **Во-первых**, в конструктор добавляем параметр (средняя цена). **Во-вторых**, записываем эту цену в текстовое поле.
 
 3. По условиям задачи мы должны вычислить среднюю цену для выделенных элементов списка (я на вскидку не нашёл как преобразовать **IList** в **IEnumerable**, поэтому тупо перебираем список выбранных элементов, считаем сумму и, заодно, собираем список идентификаторов)
 
@@ -260,7 +260,7 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
         // создаём окно, передавая ему среднюю цену    
         var NewWindow = new EnterMinCostForAgentWindow(
-            AvgSum / ProductListView.SelectedItems.Count);
+            Sum / ProductListView.SelectedItems.Count);
 
         // показываем МОДАЛЬНОЕ окно    
         NewWindow.ShowDialog();
@@ -291,64 +291,37 @@ private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs
 
 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%;">
-<a href="../articles/cs_pagination.md">Пагинация, сортировка, фильтрация, поиск
+<a href="../articles/cs_pagination2.md">Пагинация, сортировка, фильтрация, поиск
 </a></td><td style="width: 20%;">
 <a href="../readme.md">Содержание
 </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** (горизонтальный с выравниванием по правому краю)
 
@@ -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%;">
 <a href="../articles/cs_layout2.md">Вывод данных согласно макету (ListView, Image)
 </a></td><td style="width: 20%;">