Вывод данных согласно макету (ListView, Image) Содержание Подсветка элементов по условию. Дополнительные выборки.
Продолжаем реализовывать макет * [Пагинация](#пагинация) * [Сортировка](#сортировка) * [Фильтрация](#фильтрация) * [Поиск](#поиск) # Пагинация >В случае если в базе более 20 продуктов, то вывод должен осуществляться постранично (по 20 продуктов на страницу). Для удобства навигации по страницам необходимо вывести список их номеров (как на макете) с возможностью перехода к выбранной странице, а также предусмотреть переходы к предыдущей и следующей страницам. > >![](../img/product_list_layout.jpg) Критерий | Баллы ---------|:---: Данные выводятся постранично | 1 Выводится по 20 записей на странице | 0.2 Выводится список номеров страниц | 0.5 Реализован переход на выбранную в списке страницу | 0.3 Присутсвует возможность перемещаться на предыдущую и следующую страницу | 0.5 **Итого** | **2.5** ## Постраничный вывод данных Тут всё просто. Нам в любом случае придется делать геттер для фильтрованного списка продукции. Сразу в этом геттере и сделаем выборку данных порциями. Для этого используются LINQ-запросы **Skip(N)** (пропустить) и **Take(N)** (получить), где N - количество пропускаемых и выбираемых элементов соответсвенно. ```cs // тут у нас будет храниться полный список продукции private IEnumerable _ProductList; // тут мы храним текущую страницу private int _CurrentPage = 0; // при смене текущей страницы мы должны перерисовать список (вспоминайте пр INotifyPropertyChanged) private int CurrentPage { get { return _CurrentPage; } set { _CurrentPage = value; Invalidate(); } } // и реализуем геттер и сеттер списка продукции public IEnumerable ProductList { get { return _ProductList.Skip(20 * CurrentPage).Take(20); } set { _ProductList = value; Invalidate(); } } ``` ## Динамический вывод номеров страниц В принципе можно руками в разметке нарисовать эти элементы, и может даже эксперты не обратят на это внимания. Но рассмотрим всё-таки правильный вариант. 1. В разметку страницы в правую сетку под **ListView** добавьте **пустой** именованный **StackPanel** (горизонтальный с выравниванием по правому краю) ```xml ``` 2. Теперь в сеттере списка продукции динамически создадим текстовые блоки Таким образом, при любом изменении списка продукции будут перерисовываться и номера страниц ```cs set { // это остаётся как есть _ProductList = value; // очищаем содержимое пагинатора Paginator.Children.Clear(); // добавляем переход на предыдущую страницу Paginator.Children.Add(new TextBlock { Text = " < " }); // в цикле добавляем страницы for (int i = 1; i < _ProductList.Count()/20; i++) Paginator.Children.Add( new TextBlock { Text = " "+i.ToString()+" " }); // добавляем переход на следующую страницу Paginator.Children.Add(new TextBlock { Text = " > " }); // проходимся в цикле по всем сохданным элементам и задаем им обработчик PreviewMouseDown foreach (TextBlock tb in Paginator.Children) tb.PreviewMouseDown += PrevPage_PreviewMouseDown; } ``` >Можно в разметке временно создать один **TextBlock**, создать для него обработчик нажатия мыши и потом его и использовать. 3. И реализуем обработчик нажатия мыши на номерах страниц ```cs private void PrevPage_PreviewMouseDown(object sender, MouseButtonEventArgs e) { switch ((sender as TextBlock).Text) { case " < ": // переход на предыдущую страницу с проверкой счётчика if (CurrentPage > 0) CurrentPage--; return; case " > ": // переход на следующую страницу с проверкой счётчика if (CurrentPage < _ProductList.Count() / 20) CurrentPage++; return; default: // в остальных элементах просто номер странцы // учитываем, что надо обрезать пробелы (Trim) // и то, что номера страниц начинаются с 0 CurrentPage = Convert.ToInt32( (sender as TextBlock).Text.Trim() )-1; return; } } ``` # Сортировка >Пользователь должен иметь возможность отсортировать продукцию (по возрастанию и убыванию) по следующим параметрам: наименование, номер производственного цеха и минимальная стоимость для агента. Выбор сортировки должен быть реализован с помощью выпадающего списка. Критерий | Баллы ---------|:---: Реализована сортировка по названию продукции | 0.2 Реализована сортировка по номеру цеха | 0.2 Реализована сортировка по минимальной стоимости для агента | 0.2 Выбор сортировки реализован с помощью выпадающего списка | 0.5 Сортировка работает в реальном времени | 0.2 **Итого** | **1.3** В прошлом году мы делали выбор сортировки радио-кнопками, но такой вариант подходит только если сортировка по одному критерию, а у нас их три... 1. Создаем массив со списком типов сортировок ```cs public string[] SortList { get; set; } = { "Без сортировки", "название по убыванию", "название по возрастанию", "номер цеха по убыванию", "номер цеха по возрастанию", "цена по убыванию", "цена по возрастанию" }; ``` 2. В разметке добавляем элемент выпадающий список (**ComboBox**) ```xml ``` 3. Реализуем обработчик выбора из списка Запоминаем ИНДЕКС выбранного элемента ```cs private int SortType = 0; private void SortTypeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { SortType = SortTypeComboBox.SelectedIndex; Invalidate(); } ``` 4. И дорабатываем геттер списка продукции ```cs get { var Result = _ProductList; switch (SortType) { // сортировка по названию продукции case 1: Result = Result.OrderBy(p => p.Title); break; case 2: Result = Result.OrderByDescending(p => p.Title); break; // остальные сортировки реализуйте сами } return Result.Skip(20 * CurrentPage).Take(20); } ``` # Фильтрация >Кроме этого, пользователь должен иметь возможность отфильтровать данные по типу продукта. Все типы из базы данных должны быть выведены в выпадающий список для фильтрации. Первым элементом в выпадающем списке должен быть “Все типы”, при выборе которого настройки фильтра сбрасываются. Критерий | Баллы ---------|:---: Для фильтрации используется выпадающий список с типами продукции | 0.3 Первый элемент в списке "Все типы" | 0.2 Реализована фильтрация | 0.4 Фильтрация работает в реальном времени | 0.2 **Итого** | **1.1** Список типов продукции мы должны загрузить из базы данных. Если у вас ещё нет модели **ProductType**, то реализуем её и метод для получения этого списка в интерфейсе **IDataProvider** и поставщике данных (здесь я это расписывать не буду, мы это уже рассматривали в одной из предыдущих лекций, когда обсуждали вариант с получением сводных с помощью LINQ-запросов) 1. Создаем список продукции, заполняем его данными из базы и добавляем в начало пункт "Всети типы" ```cs public List ProductTypeList { get; set; } ... ProductTypeList = Globals.DataProvider.GetProductTypes().ToList(); ProductTypeList.Insert(0, new ProductType { Title = "Все типы" }); ``` 2. В разметке в верхнюю панель добавляем выпадающий список ```xml