.NET MAUI Shell 搜索
.NET Multi-platform App UI (.NET MAUI) Shell 包括 SearchHandler 类提供的集成搜索功能。 通过将 Shell.SearchHandler
附加属性设置为子类化的 SearchHandler 对象,可将搜索功能添加到页面。 这会将搜索框添加到页面顶部:
将查询输入到搜索框时,Query
属性将更新,每次更新时均将执行 OnQueryChanged
方法。 可以重写此方法来使用数据填充搜索建议区:
然后,从搜索建议区选择一个结果后,将执行 OnItemSelected
方法。 可以重写此方法来相应地进行响应,例如通过导航到详细信息页。
创建 SearchHandler
可创建 SearchHandler 类的子类,然后重写 OnQueryChanged
和 OnItemSelected
方法,将搜索功能添加到 Shell 应用:
public class AnimalSearchHandler : SearchHandler
{
public IList<Animal> Animals { get; set; }
public Type SelectedItemNavigationTarget { get; set; }
protected override void OnQueryChanged(string oldValue, string newValue)
{
base.OnQueryChanged(oldValue, newValue);
if (string.IsNullOrWhiteSpace(newValue))
{
ItemsSource = null;
}
else
{
ItemsSource = Animals
.Where(animal => animal.Name.ToLower().Contains(newValue.ToLower()))
.ToList<Animal>();
}
}
protected override async void OnItemSelected(object item)
{
base.OnItemSelected(item);
Animal animal = item as Animal;
string navigationTarget = GetNavigationTarget();
if (navigationTarget.Equals("catdetails") || navigationTarget.Equals("dogdetails"))
{
// Navigate, passing a string
await Shell.Current.GoToAsync($"{navigationTarget}?name={((Animal)item).Name}");
}
else
{
string lowerCasePropertyName = navigationTarget.Replace("details", string.Empty);
// Capitalise the property name
string propertyName = char.ToUpper(lowerCasePropertyName[0]) + lowerCasePropertyName.Substring(1);
var navigationParameters = new Dictionary<string, object>
{
{ propertyName, animal }
};
// Navigate, passing an object
await Shell.Current.GoToAsync($"{navigationTarget}", navigationParameters);
}
}
string GetNavigationTarget()
{
return (Shell.Current as AppShell).Routes.FirstOrDefault(route => route.Value.Equals(SelectedItemNavigationTarget)).Key;
}
}
OnQueryChanged
重写包含两个参数:包含旧搜索查询的 oldValue
,以及包含当前搜索查询的 newValue
。 通过将 SearchHandler.ItemsSource
属性设置为 IEnumerable
集合(其中包含与当前搜索查询匹配的项),可以更新搜索建议区。
用户选择一个搜索结果后,将执行 OnItemSelected
重写,并设置 SelectedItem
属性。 在此示例中,此方法导航到另一个显示选定的 Animal
相关数据的页面。 有关导航的详细信息,请参阅 Shell 导航。
注意
可设置其他的 SearchHandler 属性以控制搜索框的外观。
使用 SearchHandler
通过在“使用”页上将 Shell.SearchHandler
附加属性设置为子类类型对象,可以使用子类化的 SearchHandler:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler Placeholder="Enter search term"
ShowsResults="true"
DisplayMemberName="Name" />
</Shell.SearchHandler>
...
</ContentPage>
等效 C# 代码如下:
Shell.SetSearchHandler(this, new AnimalSearchHandler
{
Placeholder = "Enter search term",
ShowsResults = true,
DisplayMemberName = "Name"
});
AnimalSearchHandler.OnQueryChanged
方法返回 Animal
对象的 List
。 将 DisplayMemberName
属性设置为各个 Animal
对象的 Name
属性,这样建议区所显示的数据将为各个动物的名称。
警告
SearchHandler.DisplayMemberName
不是安全的剪裁,不应与完整修整或 NativeAOT 一起使用。 相反,应提供 ItemTemplate
来定义 SearchHandler
结果的外观。 有关详细信息,请参阅 定义搜索结果项外观、 剪裁 .NET MAUI 应用 和 本机 AOT 部署。
将 ShowsResults
属性设置为 true
,这样当用户输入搜索查询时即可显示搜索建议:
搜索查询更改时,将更新搜索建议区:
选择某个搜索结果后,将导航到 MonkeyDetailPage
,并显示有关所选猴子的详细信息页面:
定义搜索结果项外观
除了在搜索结果中显示 string
数据外,还可以通过将 SearchHandler.ItemTemplate
属性设置为 DataTemplate 来定义每个搜索结果项的外观:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler Placeholder="Enter search term"
ShowsResults="true">
<controls:AnimalSearchHandler.ItemTemplate>
<DataTemplate>
<Grid Padding="10"
ColumnDefinitions="0.15*,0.85*">
<Image Source="{Binding ImageUrl}"
HeightRequest="40"
WidthRequest="40" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</controls:AnimalSearchHandler.ItemTemplate>
</controls:AnimalSearchHandler>
</Shell.SearchHandler>
...
</ContentPage>
DataTemplate 中指定的元素定义建议区各个项的外观。 在此示例中,由 Grid 管理 DataTemplate 内的布局。 Grid 包含 Image 对象和 Label 对象,两者均绑定到各个 Monkey
对象的属性。
下面的屏幕截图显示建议区内各个项模板化后的结果:
有关数据模板的详细信息,请参阅数据模板。
搜索框可见性
默认情况下,将 SearchHandler 添加到页面顶部后,将显示并完全展开该搜索框。 但是,可以通过将 SearchHandler.SearchBoxVisibility
属性设置为 SearchBoxVisibility
枚举成员之一来更改此行为:
Hidden
– 搜索框不可见或不可访问。Collapsible
– 隐藏搜索框,直到用户执行操作来显示搜索框。 在 iOS 上,通过纵向弹跳页面内容来显示搜索框;在 Android 上,通过点击问号图标显示搜索框。Expanded
– 搜索框可见,并且完全展开。 这是SearchBoxVisibility
属性的默认值。
重要
在 iOS 上,可折叠搜索框需要 iOS 11 或更高版本。
下面的示例演示了如何隐藏搜索框:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler SearchBoxVisibility="Hidden"
... />
</Shell.SearchHandler>
...
</ContentPage>
搜索框焦点
点击搜索框可调用屏幕键盘,使搜索框获得输入焦点。 也可以通过调用 Focus
方法(尝试在搜索框上设置输入焦点,并在成功时返回 true
)来以编程方式实现。 当搜索框获得焦点时,会触发 Focused
事件并调用可重写的 OnFocused
方法。
当搜索框具有输入焦点时,点击屏幕上的其他位置可关闭屏幕键盘,并且搜索框失去输入焦点。 也可以通过调用 Unfocus
方法来以编程方式实现。 当搜索框失去焦点时,会触发 Unfocused
事件并调用可重写的 OnUnfocus
方法。
可以通过 IsFocused
属性检索搜索框的焦点状态,如果 SearchHandler 当前具有输入焦点,则会返回 true
。
SearchHandler 键盘
用户与 SearchHandler 交互时显示的键盘可以通过 Keyboard
属性以编程方式设置为 Keyboard
类中的以下属性之一:
Chat
– 用于可使用表情符号的文本和位置。Default
– 默认键盘。Email
– 输入电子邮件地址时使用。Numeric
– 输入数字时使用。Plain
– 输入文本时使用,无需指定任何KeyboardFlags
。Telephone
– 输入电话号码时使用。Text
– 输入文本时使用。Url
– 用于输入文件路径和 Web 地址。
这可以通过以下操作以 XAML 实现:
<SearchHandler Keyboard="Email" />
Keyboard
类还具有 Create
工厂方法,可用于通过指定大小写、拼写检查和建议行为来自定义键盘。 KeyboardFlags
枚举值指定为方法的参数,并返回自定义的 Keyboard
。 KeyboardFlags
枚举包含以下值:
None
– 无功能添加到键盘。CapitalizeSentence
– 指示自动大写输入的每句话的第一个词的首字母。Spellcheck
– 指示对输入的文本执行拼写检查。Suggestions
– 指示对输入的文本执行单词自动完成。CapitalizeWord
– 指示自动大写每个词的首字母。CapitalizeCharacter
– 指示自动大写每个字符。CapitalizeNone
– 指示不执行自动大写。All
– 指示对输入的文本执行拼写检查、单词自动完成和句子首字母大写。
以下 XAML 代码示例演示如何自定义默认 Keyboard
来执行单词自动完成并将输入的每个字符的首字母大写:
<SearchHandler Placeholder="Enter search terms">
<SearchHandler.Keyboard>
<Keyboard x:FactoryMethod="Create">
<x:Arguments>
<KeyboardFlags>Suggestions,CapitalizeCharacter</KeyboardFlags>
</x:Arguments>
</Keyboard>
</SearchHandler.Keyboard>
</SearchHandler>