Búsqueda en aplicaciones Shell .NET MAUI
La interfaz de usuario de aplicaciones Shell multiplataforma .NET (.NET MAUI) incluye la funcionalidad de búsqueda integrada que proporciona la clase SearchHandler. Se puede agregar funcionalidad de búsqueda a una página estableciendo la propiedad adjunta Shell.SearchHandler
en un objeto SearchHandler con subclases. El resultado es un cuadro de búsqueda que se agrega en la parte superior de la página:
Cuando se escribe una consulta en el cuadro de búsqueda, la propiedad Query
se actualiza y, en cada actualización, se ejecuta el método OnQueryChanged
. Este método se puede invalidar para rellenar el área de sugerencias de búsqueda con datos:
Luego, cuando se seleccione un resultado del área de sugerencias de búsqueda, se ejecutará el método OnItemSelected
. Este método se puede invalidar para responder de forma adecuada; por ejemplo, navegando a una página de detalles.
Creación de una clase SearchHandler
La funcionalidad de búsqueda se puede agregar a una aplicación Shell mediante la creación de subclases de la clase SearchHandler y la invalidación de los métodos OnQueryChanged
y OnItemSelected
:
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;
}
}
La invalidación OnQueryChanged
tiene dos argumentos: oldValue
, que contiene la consulta de búsqueda anterior, y newValue
, que contiene la consulta de búsqueda actual. El área de sugerencias de búsqueda se puede actualizar mediante el establecimiento de la propiedad SearchHandler.ItemsSource
en una colección IEnumerable
que contiene elementos que coinciden con la consulta de búsqueda actual.
Cuando el usuario selecciona un resultado de búsqueda, se ejecuta la invalidación OnItemSelected
y se establece la propiedad SelectedItem
. En este ejemplo, el método dirige a otra página que muestra datos sobre el elemento Animal
seleccionado. Para obtener más información sobre la navegación, consulte Navegación en Shell.
Nota:
Se pueden establecer propiedades SearchHandler adicionales para controlar la apariencia del cuadro de búsqueda.
Consumo de una clase SearchHandler
La clase SearchHandler con subclases se puede consumir mediante el establecimiento de la propiedad adjunta Shell.SearchHandler
en un objeto del tipo con subclases, en la página de consumo:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler Placeholder="Enter search term"
ShowsResults="true"
DisplayMemberName="Name" />
</Shell.SearchHandler>
...
</ContentPage>
El código de C# equivalente es el siguiente:
Shell.SetSearchHandler(this, new AnimalSearchHandler
{
Placeholder = "Enter search term",
ShowsResults = true,
DisplayMemberName = "Name"
});
El método AnimalSearchHandler.OnQueryChanged
devuelve un elemento List
de objetos Animal
. La propiedad DisplayMemberName
se establece en la propiedad Name
de cada objeto Animal
, por lo que los datos mostrados en el área de sugerencias serán el nombre de cada animal.
Advertencia
SearchHandler.DisplayMemberName
no es seguro recortar y no debe usarse con recorte completo ni NativeAOT. En su lugar, debes proporcionar un ItemTemplate
para definir la apariencia de los resultados SearchHandler
. Para obtener más información, vea Definir la apariencia del elemento de resultados de búsqueda, Recortar una aplicación MAUI de .NET y una implementación de AOT nativa.
La propiedad ShowsResults
está establecida en true
, de modo que se muestran sugerencias de búsqueda cuando el usuario escribe una consulta de búsqueda:
A medida que cambia la consulta de búsqueda, se actualiza el área de sugerencias de búsqueda:
Cuando se selecciona un resultado de la búsqueda, se navega a MonkeyDetailPage
y se muestra una página de detalles del mono seleccionado:
Definición de la apariencia de los elemento de los resultados de búsqueda
Además de mostrar datos de string
en los resultados de la búsqueda, se puede definir la apariencia de cada uno de los elementos de los resultados de la búsqueda mediante el establecimiento de la propiedad SearchHandler.ItemTemplate
en 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>
Los elementos especificados en DataTemplate definen la apariencia de cada elemento en el área de sugerencias. En este ejemplo, el diseño dentro de DataTemplate se administra mediante un objeto Grid. El objeto Grid contiene un objeto Image y un objeto Label, que enlazan ambos con las propiedades de cada objeto Monkey
.
Las capturas de pantalla siguientes muestran el resultado de crear plantillas para cada elemento del área de sugerencias:
Para obtener más información sobre las plantillas de datos, consulta Plantillas de datos.
Visibilidad del cuadro de búsqueda
Cuando se agrega un objeto SearchHandler en la parte superior de una página, el cuadro de búsqueda está visible y totalmente expandido de forma predeterminada. Pero este comportamiento se puede cambiar estableciendo la propiedad SearchHandler.SearchBoxVisibility
en uno de los miembros de la enumeración SearchBoxVisibility
:
Hidden
: el cuadro de búsqueda no es visible ni accesible.Collapsible
: el cuadro de búsqueda está oculto hasta que el usuario realiza una acción para mostrarlo. En iOS, el cuadro de búsqueda aparece rebotando verticalmente el contenido de la página y, en Android, el cuadro de búsqueda aparece al pulsar el icono del signo de interrogación.Expanded
: el cuadro de búsqueda está visible y totalmente expandido. Se trata del valor predeterminado de la propiedadSearchBoxVisibility
.
Importante
En iOS, un cuadro de búsqueda contraíble requiere iOS 11 o superior.
En el ejemplo siguiente se muestra cómo ocultar el cuadro de búsqueda:
<ContentPage ...
xmlns:controls="clr-namespace:Xaminals.Controls">
<Shell.SearchHandler>
<controls:AnimalSearchHandler SearchBoxVisibility="Hidden"
... />
</Shell.SearchHandler>
...
</ContentPage>
Enfoque en el cuadro de búsqueda
Al pulsar en un cuadro de búsqueda aparece el teclado en pantalla, y el cuadro de búsqueda adquiere el foco de entrada. Esto también se consigue mediante programación llamando al método Focus
, que intenta establecer el foco de entrada en el cuadro de búsqueda y, si se realiza correctamente, devuelve true
. Cuando un cuadro de búsqueda obtiene el foco, se desencadena el evento Focused
y se llama al método OnFocused
reemplazable.
Cuando un cuadro de búsqueda tiene el foco de entrada, al pulsar en otro lugar en la pantalla desaparece el teclado en pantalla y el cuadro de búsqueda pierde el foco de entrada. Esto también se consigue mediante programación llamando al método Unfocus
. Cuando un cuadro de búsqueda pierde el foco, se desencadena el evento Unfocused
y se llama al método OnUnfocus
reemplazable.
Se puede recuperar el estado del foco de un cuadro de búsqueda a través de la propiedad IsFocused
, que devuelve true
si un objeto SearchHandler tiene actualmente el foco de entrada.
Teclado SearchHandler
El teclado que aparece cuando los usuarios interactúan con un objeto SearchHandler se puede establecer mediante programación a través de la propiedad Keyboard
en una de las siguientes propiedades de la clase Keyboard
:
Chat
: se usa para el texto y los lugares donde los emoji son útiles.Default
: el teclado predeterminado.Email
: se usa al especificar direcciones de correo electrónico.Numeric
: se usa al escribir números.Plain
: se usa al escribir texto, sin ningúnKeyboardFlags
especificado.Telephone
: se usa al escribir números de teléfono.Text
: se usa al escribir texto.Url
: se usa para especificar las rutas de acceso de archivo y direcciones web.
Esto se puede lograr en XAML de la siguiente manera:
<SearchHandler Keyboard="Email" />
La clase Keyboard
tiene también un patrón de diseño Factory Method Create
que puede usarse para personalizar un teclado mediante la especificación del comportamiento de las mayúsculas y minúsculas, el corrector ortográfico y las sugerencias. Los valores de enumeración KeyboardFlags
se especifican como argumentos para el método, con la devolución de un Keyboard
personalizado. La enumeración KeyboardFlags
contiene los valores siguientes:
None
: no se agregan características al teclado.CapitalizeSentence
: indica que la primera letra de la primera palabra de cada frase se escribirá automáticamente en mayúsculas.Spellcheck
: indica que se pasará el corrector ortográfico al texto especificado.Suggestions
: indica que se ofrecerán finalizaciones de palabra para el texto especificado.CapitalizeWord
: indica que las primeras letras de todas las palabras se escribirán automáticamente en mayúsculas.CapitalizeCharacter
: indica que todos los caracteres se escribirán automáticamente en mayúsculas.CapitalizeNone
: indica que no se producirá ningún uso automático de mayúsculas.All
: indica que se pasará el corrector automático, se ofrecerán finalizaciones de palabras y las frases empezarán en mayúsculas en el texto especificado.
El ejemplo de código XAML siguiente muestra cómo personalizar el Keyboard
predeterminado para ofrecer finalizaciones de palabras y poner en mayúsculas todos los caracteres especificados:
<SearchHandler Placeholder="Enter search terms">
<SearchHandler.Keyboard>
<Keyboard x:FactoryMethod="Create">
<x:Arguments>
<KeyboardFlags>Suggestions,CapitalizeCharacter</KeyboardFlags>
</x:Arguments>
</Keyboard>
</SearchHandler.Keyboard>
</SearchHandler>