Créer une liste et sa recherche associée

Ajouté par Alexandre Journaux il y a presque 3 ans

Dans ce tuto, nous allons voir comment faire ceci :

Pour cela, nous aurons besoin d'utiliser 2 objets dans Xaml SearchBar et ListView :
<StackLayout>
    <SearchBar x:Name="monSearchBar" SearchCommand="{Binding SearchPersonneCommand}" 
                                  SearchCommandParameter="{Binding Text, Source={x:Reference monSearchBar}}" />
    <ListView ItemsSource="{Binding Personnes}" />
</StackLayout>

Un peu d'explication sur le code précédent :
Pour la ListView c'est facile, un simple Binding sur une liste de personnes qui est nommée : Personnes
Pour l'objet SearchBar, c'est un peu plus compliqué :
  • D'abord, il y a l'attribut SearchCommand qui est bindé avec une commande. C'est cette commande qui fera le filtre sur la liste en fonction de ce qui est saisi.
  • Ensuite, il y a l'attribut SearchCommandParameter qui a un binding un peu bizarre. Cet attribut correspond au paramètre qui sera envoyé à la commande du SearchCommand.
    Et ce paramètre correspond à la propriété Text de l'objet passé en référence (qui s'appelle monSearchBar). Donc on va bien envoyer, en paramètre de la commande, le texte saisi dans le SearchBar.

Le code dans le ViewModel est assez simple, il consiste à filtrer la liste en fonction de ce qui est saisi.

public class TestSearchViewModel : BaseViewModel
{
    public ICommand SearchPersonneCommand { get; private set; }

    public TestSearchViewModel()
    {
        SearchPersonneCommand = new Command<string>(SearchPersonne);
        personnes = new List<string>();
        initListePersonnes();
    }

    private void SearchPersonne(string query)
    {
        initListePersonnes();
        IEnumerable<String> searchresult = personnes.Where(p => p.ToUpper().Contains(query.ToUpper()));
        Personnes = new List<string>(searchresult);
    }

Ce code fonctionne très bien MAIS l'utilisateur doit valider sa saisie pour qu'elle soit prise en compte par la commande.
Or ce qu'on aimerait c'est que la saisie soit prise en compte au fur et à mesure. Pour cela, on va modifier le comportement de l'objet SearchBar afin qu'il lance la commande dès que le texte change (évènement TextChanged). On va donc créer un Behavior (Cf. le post Behavior qu’es aquò ? ).

public class TextChangedBehavior : Behavior<Xamarin.Forms.SearchBar>
{
    protected override void OnAttachedTo(SearchBar bindable)
    {
        bindable.TextChanged += Bindable_TextChanged;
    }

    protected override void OnDetachingFrom(SearchBar bindable)
    {
        bindable.TextChanged -= Bindable_TextChanged;
    }

    private void Bindable_TextChanged(object sender, TextChangedEventArgs e)
    {
        Xamarin.Forms.SearchBar sb = (Xamarin.Forms.SearchBar)sender;
        sb.SearchCommand.Execute(e.NewTextValue);
    }
}

Il ne reste plus qu'à renseigner ce Behavior dans le fichier Xaml :

<SearchBar x:Name="monSearchBar" SearchCommand="{Binding SearchPersonneCommand}" 
                                 SearchCommandParameter="{Binding Text, Source={x:Reference monSearchBar}}" >
        <SearchBar.Behaviors>
            <behaviors:TextChangedBehavior/>
        </SearchBar.Behaviors>
</SearchBar>

Et voilà notre liste est filtrée au fur et à mesure de la saisi.

searchbar.jpg (77,966 ko)