Предыдущая лекция | &nbsp; | Следующая лекция
:----------------:|:----------:|:----------------:
[Фильтрация данных](./wpf_filtering.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Вывод данных согласно макета (ListBox, Image)](./wpf_listbox.md)

# Поиск, сортировка

В этой теме мы познакомимся ещё с двумя визуальными элементами: **TextBox** (ввод строки для поиска) и **RadioButton** (сортировка по одному полю)

## Поиск

1. В разметке окна (в элемент **WrapPanel**) добавляем элемент для ввода теста - **TextBox**

    ```xml
    <Label 
        Content="искать" 
        VerticalAlignment="Center"/>
    <TextBox
        Width="200"
        VerticalAlignment="Center"
        x:Name="SearchFilterTextBox" 
        KeyUp="SearchFilter_KeyUp"/>
    ```    

    Не забываем реализовать (`^ + пробел`) обработчик события _KeyUp_ (этот обработчик срабатывает при отпускании клавиши)

1. В коде окна создаем переменную для хранения строки поиска и запоминаем её в обработчике ввода текста (SearchFilter_KeyUp)

    ```cs
    private string searchFilter = ""; 

    private void SearchFilter_KeyUp(object sender, KeyEventArgs e)
    {
        searchFilter = SearchFilterTextBox.Text;
        Invalidate();
    }
    ```

1. Дорабатываем геттер списка кошек, чтобы после фильтра срабатывал ещё и поиск по кличке

    ```cs
    get
    {
        // сохраняем во временную переменную полный список
        var res = _catList;

        // фильтруем (тут только один вариант, у вас может быть несколько)
        res = res.Where(c => (
            c.age >= selectedAge.ageFrom && 
            c.age < selectedAge.ageTo
        ));

        // если строка поиска не пуста, то ищем ВХОЖДЕНИЕ подстроки поиска в кличке без учета регистра
        if(searchFilter != "")
            res = res.Where(c => c.name.IndexOf(
                searchFilter, 
                StringComparison.OrdinalIgnoreCase) >= 0);

        return res;
    }
    ```

    Метод **IndexOf** возвращает позицию подстроки в строке или `-1`, если подстрока не найдена. В доке есть метод **Contains**, но он доступен только с версии .NET 9

## Сортировка

>Мы, в рамках знакомства с визуальными элементами, будем использовать радио-кнопки, но, если вариантов сортировки более одного, то лучше использовать тот-же выпадающий список

Мы будем сортировать по возрасту

Выбранный вариант будем определять по атрибуту **Tag**. Этот атрибут есть у всех визуальных элементов и его тип **объект**. 

1. В разметке добавляем радиокнопки

    ```xml
    <Label 
        Content="Возраст:" 
        VerticalAlignment="Center"/>
    <RadioButton
        GroupName="Age"
        Tag="1"
        Content="по возрастанию"
        IsChecked="True"
        Checked="RadioButton_Checked"
        VerticalAlignment="Center"/>
    <RadioButton
        GroupName="Age"
        Tag="2"
        Content="по убыванию"
        Checked="RadioButton_Checked"
        VerticalAlignment="Center"/>
    ```

    У группы радио-кнопок одновременно может быть выбран только один вариант. Группа задается атрибутом **GroupName** 

1. В коде добавляем переменную для хранения варианта сортировки и обработчик смены варианта сортировки

    >Мы в атрибуте **Tag** храним просто уникальное значение, но при необходимости можем *прибиндить* какой-нибудь объект и в обработчике получить его: `(sender as RadioButton).Tag as SomeClass`.

    ```cs
    private bool sortAsc = true;

    private void RadioButton_Checked(object sender, RoutedEventArgs e)
    {
        sortAsc = (sender as RadioButton).Tag.ToString() == "1";
        Invalidate();
    }
    ```

1. И дорабатываем геттер списка кошек

    ```cs
    ...
    if (sortAsc) res = res.OrderBy(c => c.age);
    else res = res.OrderByDescending(c => c.age);

    return res;
    ```

---

## Задание

Реализовать пример из лекции в проекте "кошки"

Предыдущая лекция | &nbsp; | Следующая лекция
:----------------:|:----------:|:----------------:
[Фильтрация данных](./wpf_filtering.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Вывод данных согласно макета (ListBox, Image)](./wpf_listbox.md)
