XAML .NET MAUI -多个Shell,是否可能使用SearchHandler?

wnvonmuf  于 2022-12-07  发布在  .NET
关注(0)|答案(2)|浏览(242)

我在选项卡式MAUI应用程序中使用了Shell.SearchHandler(.NET 6)。我将应用程序初始化到一个特定的页面,您可以在该页面中通过API搜索一组“外部联系人”。我还有一个额外的页面,用于通过API搜索一组“系统用户”。当应用程序初始化时,如果我导航到“用户”页面,它不会更新搜索处理程序,搜索功能仍然使用初始页面的模板。
是否可以修改每个页面上的模板?
ContactsPage.xaml

<Shell.SearchHandler>
        <controls:ExternalContactSearchHandler Placeholder="Enter last name"
                                  ShowsResults="true"
                                  ItemTemplate="{StaticResource ExternalContactSearchTemplate}"
                                  ExternalContacts="{x:Static data:ExternalContactData.ExternalContacts}"
                                  SelectedItemNavigationTarget="{x:Type views:ContactDetailPage}" />
    </Shell.SearchHandler>

Users.xaml

<Shell.SearchHandler>
        <controls:UserSearchHandler Placeholder="Enter User Name"
                                  ShowsResults="true"
                                  ItemTemplate="{StaticResource UserSearchTemplate}"
                                  Users="{x:Static data:UserData.Users}"
                                  SelectedItemNavigationTarget="{x:Type views:UserDetailPage}" />
    </Shell.SearchHandler>

App.xaml

<DataTemplate x:Key="UserSearchTemplate">
            <Grid Padding="10" 
                  ColumnDefinitions="0.15*,0.85*">
                <Image Source="{Binding Images[1].ImageUri}"
                       HeightRequest="40"
                       WidthRequest="40" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       VerticalOptions="Center" />
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="ExternalContactSearchTemplate">
            <Grid Padding="10" ColumnDefinitions="Auto,Auto,Auto">
                <Label Grid.Column="0"
                       Text="{Binding FirstName}"
                       FontAttributes="Bold"
                       HorizontalOptions="Start"
                       VerticalOptions="Center" />
                <Label Grid.Column="1"
                       Text="{Binding LastName}"
                       FontAttributes="Bold"
                       HorizontalOptions="Start"
                       VerticalOptions="Center" />
                <Label Grid.Column="2"
                       Text="{Binding Title}"
                       FontAttributes="Bold"
                       HorizontalOptions="End"
                       VerticalOptions="Center" />
            </Grid>
        </DataTemplate>
k5ifujac

k5ifujac1#

这当然很有趣,因为我假定在每个页面中设置SearchHandler会解决这个问题,但是我将各个页面中的Shell.SearchHandler XAML移到了C#中(如下),而且它仍然只利用了使用的第一个。我很困惑。我是否需要每次都从头开始重建整个 shell 或其他什么?我并不反对在渲染之前将所有这些都移到代码vs XAML中,但这似乎是不必要的,只是感觉我错过了什么。
Users.xaml.cs

public UsersPage()
    {
        InitializeComponent();

        Shell.SetSearchHandler(this, new UserSearchHandler
        {
            Placeholder = "Enter first or last name",
            ShowsResults = true,
            SelectedItemNavigationTarget = typeof(UserDetailPage),
            Users = UserData.Users,
            ItemTemplate = new DataTemplate(() =>
            {
                Grid grid = new Grid { Padding = 10 };
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.15, GridUnitType.Star) });
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.85, GridUnitType.Star) });

                Image image = new Image { HeightRequest = 40, WidthRequest = 40 };
                image.SetBinding(Image.SourceProperty, "Images[1].ImageUri");
                Label nameLabel = new Label { FontAttributes = FontAttributes.Bold, VerticalOptions = LayoutOptions.Center };
                nameLabel.SetBinding(Label.TextProperty, "Name");

                grid.Children.Add(image);
                grid.Children.Add(nameLabel);

                return grid;
            })
        });
    }

ContactsPage.xaml.cs

public ContactsPage()
    {
        InitializeComponent();

        Shell.SetSearchHandler(this, new ExternalContactSearchHandler
        {
            Placeholder = "Enter search term",
            ShowsResults = true,
            SelectedItemNavigationTarget = typeof(UserDetailPage),
            ExternalContacts = ExternalContactData.ExternalContacts,
            ItemTemplate = new DataTemplate(() =>
            {
                Grid grid = new Grid { Padding = 10 };
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

                Label firstNameLabel = new Label { FontAttributes = FontAttributes.Bold, HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.Center };
                firstNameLabel.SetBinding(Image.SourceProperty, "FirstName");
                Label lastNameLabel = new Label { FontAttributes = FontAttributes.Bold, HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.Center };
                lastNameLabel.SetBinding(Label.TextProperty, "LastName");
                Label titleLabel = new Label { FontAttributes = FontAttributes.Bold, HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Center };
                titleLabel.SetBinding(Label.TextProperty, "Title");

                grid.Children.Add(firstNameLabel);
                grid.Children.Add(lastNameLabel);
                grid.Children.Add(titleLabel);

                return grid;
            })
        });
    }
hmmo2u0o

hmmo2u0o2#

Shell.SetSearchHandler会影响整个Shell。它是全域的。当您呼叫它时,所有的页面都会受到影响。
将它放在构造函数中是无效的,因为在加载Shell时调用了该构造函数:所有的页面都被“构造”了,即使是那些还看不见的页面。

未来:修复“MAUI错误-未对选项卡页调用OnAppearing”时

将以Shell.SetSearchHandler...开头的代码移到每个页面的OnAppearing方法中。该方法在该页面即将可见时运行:

protected override void OnAppearing(...)
{
    base.OnAppearing();

    Shell.SetSearchHandler...
    ...
}

替代解决方案

Shell有一个Navigating事件,在转到新页面时调用该事件。使用此事件可根据导航到的页面设置不同的搜索处理程序:

protected override void OnNavigating(ShellNavigatingEventArgs args)
{
    base.OnNavigating(args);

    // Test which page is next.
    if (args.Target == /*...uri of your page...*/)
    {
        // ... your code here to set search handler ...
    }
}

相关问题