Shell. Организация поиска в приложении (SearchHandler)

Класс Shell позволяет нам использовать интегрированный обработчик поиска в приложении, используя который, мы можем организовать поиск любых данных в нашем приложении. В этой части мы разберемся с тем, как организовать поиск в нашем приложении с использованием наследников класса SearchHandler.

Организация поиска в приложении

Создание обработчика (наследника класса SearchHandler)

Чтобы задействовать систему поиска в приложении .NET MAUI мы должны создать свой класс-наследник класса SearchHandler. Этот класс содержит достаточно много различных свойств и методов, поэтому имеет смысл разобраться с его работой последовательно, начав с главного — организации поиска в приложении.

Итак создайте новое приложение .NET MAUI или воспользуйтесь исходным кодом приложения, которое мы используем на протяжении всего этого раздела. Создадим в проекте новую папку с названием Controls и разместим в ней класс PageSearchHandler:

Код класса будет следующим:

namespace AppShellEx.Controls
{
    class PageSearchHandler: SearchHandler
    {
        public List<string> Pages { get; set; }

        protected override void OnQueryChanged(string oldValue, string newValue)
        {
            base.OnQueryChanged(oldValue, newValue);

            if (string.IsNullOrWhiteSpace(newValue))
            {
                ItemsSource = null;
            }
            else
            {
                ItemsSource = Pages.Where(page => page.ToLower().Contains(newValue.ToLower()))
                    .ToList<string>();
            }
        }

        protected override async void OnItemSelected(object item)
        {
            base.OnItemSelected(item);

            await Shell.Current.GoToAsync($"///{page}");
        }
    }
}

Рассмотрим этот класс подробно. Итак, класс PageSearchHandler является наследником класса SearchHandler. Свойство Pages будет содержать маршруты (свойство ShellContent.Route страниц приложения). По этому списку мы будем проводить поиск.

Далее мы переопределили у базового класса метод OnQueryChanged(). Этот метод вызывается каждый раз при изменении поискового запроса и содержит два параметра:

  • oldValue — предыдущее значение, заданное пользователем в поисковой строке
  • newValue — новое значение

В этом методе мы производим поиск по списку Page текущего значения из строки поиска и присваиваем полученную коллекцию свойству ItemsSource, которое должно содержать все найденные элементы:

ItemsSource = Pages.Where(page => page.ToLower().Contains(newValue.ToLower()))
    .ToList<string>();

если поисковая строка не содержит никаких элементов, то свойству ItemSource присваивается значение null.

Второй переопределенный метод OnItemSelected() вызывается каждый раз, когда пользователь выбирает какой-либо элемент в списке найденных элементов. При этом параметр item содержит выбранный пользователем элемент. В этом методе мы осуществляем переход на найденную страницу, используя метод GoToAsync() класса Shell. Об этом и других методах навигации мы поговорим позднее, когда будем разбирать вопросы, связанные с навигацией в приложениях .NET MAUI.

Использование обработчика в приложении

Теперь нам необходимо использовать созданный обработчик поиска в тех местах приложения где необходимо организовать поиск. Например, добавим его на главную страницу приложения. Изменим код страницы MainPage следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AppShellEx.MainPage"
             Title="MainPage"
             xmlns:controls="clr-namespace:AppShellEx.Controls">

    <Shell.SearchHandler>
        <controls:PageSearchHandler x:Name="Search">
            
        </controls:PageSearchHandler>
    </Shell.SearchHandler>
....

</ContentPage>

Первое, что мы здесь сделали — это подключили новое пространство имен в котором расположен обработчик:

xmlns:controls="clr-namespace:AppShellEx.Controls"

Далее мы, используя свойство Shell.SearchHandler добавили на страницу наш обработчик, присвоив ему через атрибут x:Name имя Search (имя можно задавать любое). Теперь нам необходимо определить в обработчике значение свойства Pages, чтобы поиск заработал.

Здесь будет показан один (не самый лучший) способ как это сделать, но в дальнейшем, когда мы разберемся с привязкой в .NET MAUI, вы сможете воспользоваться другим, более рациональным, способом определения свойств элементов в XAML

Откроем файл отдельного кода MainPage.xaml.cs и изменим его следующим образом:

namespace AppShellEx
{
    public partial class MainPage : ContentPage
    {
        public List<string> Pages = ["MainPage", "DetailPage"];
        
        int count = 0;

        public MainPage()
        {
            InitializeComponent();
            Search.Pages = Pages;
        }
        ....
    }
}

То есть мы передаем в свойство Pages нашего обработчика поиска список Pages непосредственно в конструкторе класса. Следующий шаг — это определить маршруты страниц. Для этого откроем файл AppShell.xaml и изменим его следующим образом:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="AppShellEx.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:AppShellEx"
    Title="AppShellEx"
    BackgroundColor ="Coral"
    TitleColor ="Red">

    <ShellContent Title="1"  
                  ContentTemplate="{DataTemplate local:MainPage}"
                  Route="MainPage"/>
    <ShellContent Title="2" 
                  ContentTemplate="{DataTemplate local:DetailPage}"
                  Route="DetailPage"/>
        
</Shell>

Обратите внимание на то, что значения свойств Route у нас полностью совпадает со значениями из переданного в PageSearchHandler списка. Теперь можно проверить работу поиска в нашем приложении. Запустите приложение и попробуйте набрать в строке поиска, например, символ «D»:

Вы увидите, что под строкой поиска открывается список, но без какого-либо текста. При этом, если вы выберите в этом списке пустой элемент, то вы действительно будете перемещены на страницу DetailPage. То есть сам по себе поиск работает и нам остается только разобраться с тем как отобразить результаты поиска.

Отображение результатов поиска

Чтобы в списке появлялись данные о найденных элементах, нам необходимо определить в нашем обработчике поиска свойство ItemTemplate — шаблон найденных элементов. Здесь нам снова придется немного «забежать вперед». Изменим XAML-код обработчика поиска следующим образом:

<Shell.SearchHandler>
    <controls:PageSearchHandler x:Name="Search">
        <controls:PageSearchHandler.ItemTemplate>
            <DataTemplate x:DataType="x:String">
                <Label Text="{Binding}"
                       FontAttributes="Bold" 
                       VerticalOptions="Center" />
            </DataTemplate>
        </controls:PageSearchHandler.ItemTemplate>
    </controls:PageSearchHandler>
</Shell.SearchHandler>

Рассмотрим этот код с последнего элемента. Итак, для отображения результатов поиска мы задействуем элемента Label:

<Label Text="{Binding}" FontAttributes="Bold" VerticalOptions="Center" />

У этого элемента в качестве значения для свойства Text указано {Binding}. Это, проще говоря, означает, что свойству Text будет присваиваться весь объект, который мы привязываем. А привязываем мы то, что нашел наш обработчик поиска.

Элемент Label «обернут» в DataTemplate (шаблон данных), который определяет как привязанный объект должен быть отображен. У DataTemplate мы определили атрибут x:DataType="x:String", который говорит, что в качестве данных для отображения выступает обычная строка.

И, наконец, вся эта конструкция из DataTemplate и Label выступает в качестве шаблона для элемента списка поиска — значения для свойства ItemTemplate. Таким образом, наша система поиска будет работать следующим образом: после того, как получены данные в ItemSource, каждый элемент этого свойства будет использоваться в качестве значения для Label и отображаться в списке.

Запустим приложение и снова проверим его работу:

Как можно видеть по рисунку, теперь наша система поиска заработала так, как и должна — в списке отображаются найденные элементы, а выбор очередного элемента позволяет перейти на страницу приложения. Теперь можно украсть наш поиск. Для этого разберемся с другими свойствами класса SearchHandler

Итого

Для организации поиска в приложении мы должны создать класс-наследник для класса SearchHandler, у которого переопределить методы OnQueryChanged() и OnItemSelected(). Чтобы результаты поиска корректно отображались в списке найденных элементов, у компонента поиска необходимо определить свойство ItemTemplate.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии