WPF: AutoCompleteBox, caixa de texto com autocomplete

O WPF Toolkit inclui o controlo AutoCompleteBox. Como o nome sugere, é um controlo para uma caixa de texto com autocomplete. Neste artigo mostramos como instalar o toolkit e como usar a AutoCompleteBox.

1. Instalar o WPF Toolkit

O primeiro passo é instalar o WPF Toolkit. Podem fazer download do installer ou instalá-lo directamente a partir do NuGet package manager no Visual Studio.

Instalar o WPF Toolkit a partir do NuGet
Instalar o WPF Toolkit a partir do NuGet

2. Declarar o namespace correcto

A AutoCompleteBox está na assembly System.Windows.Controls.Input.Toolkit.dll. Significa que têm de usar o seguinte namespace:

xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"

3. Adicionar a AutoCompleteBox a uma view

Suponhamos que temos o seguinte view model:

public interface IYourViewModel
{
    IEnumerable<string> Names { get; }
    string SelectedName { get; set; }
}

Adicionamos o controlo da AutoCompleteBox da seguinte maneira:

<toolkit:AutoCompleteBox
    ItemsSource="{Binding Names}"
    SelectedItem="{Binding SelectedName, Mode=TwoWay}" />

Quando a selecção muda, a propriedade SelectedName será actualizada.

O resultado deverá ser parecido ao seguinte:

Exemplo da AutoCompleteBox
Exemplo da AutoCompleteBox

4. Personalizar a AutoCompleteBox

Eis algumas propriedades que permitem personalizar a experiência do utilizador:

  • IsTextCompletionEnabled: permite a parte do “autocomplete”. Se estiver activo, o primeiro resultado será seleccionado automaticamente assim que o utilizador começar a escrever.
  • FilterMode: define o tipo de autocomplete, e.g.: StartsWith, Contains, Equals.
  • MinimumPrefixLength: o número mínimo de caracteres a partir do qual as sugestões vão começar a aparecer.

5. Usar a AutoCompleteBox com classes

Vamos agora considerar que queremos usar objectos em vez de um conjunto de strings.

public class Person
{
    public DateTime Birthday { get; set; }
    public string Name { get; set; }
}

O view model não se altera muito:

public interface IPeopleViewModel
{
    IEnumerable<Person> People { get; }
    Person SelectedPerson { get; set; }
}

Ao usar o controlo especificam a propriedade ValueMemberPath ou ValueMemberBinding para indicar que campo será usado para a pesquisa e também para ser mostrado na caixa de texto.

<toolkit:AutoCompleteBox
    ItemsSource="{Binding People}"
    SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"
    ValueMemberPath="Name"
    ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}" />

Como estamos a usar objectos agora, temos de especificar um template, senão será usado o método ToString para a visualização.

<DataTemplate x:Key="AutoCompleteBoxItemTemplate">
    <StackPanel Orientation="Horizontal">
        <Label
            Content="{Binding Name}"
            Width="100" />
        <Label
            Content="{Binding Birthday}"
            FontStyle="Italic"
            Foreground="DarkGray" />
    </StackPanel>
</DataTemplate>

Neste exemplo apenas mostramos o nome seguido do aniversário.

AutoCompleteBox com um ItemTemplate custom
AutoCompleteBox com um ItemTemplate custom

6. Pesquisar em mais do que um campo

Agora já sabem usar a AutoCompleteBox com objectos, mas querem mudar a forma como a filtração é efectuada. Podem fazer isso usando a propriedade ItemFilter, que espera um delegate AutoCompleteFilterPredicate<object>.

Vamos assumir que a classe Person agora tem as propriedades FirstName e LastName e que querem filtrar os itens baseando-se nessas duas propriedades.

public class Person
{
    public DateTime Birthday { get; set; }
    public string Name { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Criam o predicado no view model:

public AutoCompleteFilterPredicate<object> PersonFilter
{
    get
    {
        return (searchText, obj) =>
            (obj as Person).FirstName.Contains(searchText)
            || (obj as Person).LastName.Contains(searchText);
    }
}

E depois definem a propriedade na AutoCompleteBox:

<toolkit:AutoCompleteBox
    ItemsSource="{Binding People}"
    SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"
    ValueMemberPath="Name"
    ItemTemplate="{StaticResource AutoCompleteBoxItemTemplate}"
    ItemFilter="{Binding PersonFilter}" />

Voilá!

AutoCompleteBox com ItemFilter
AutoCompleteBox com ItemFilter

Artigos relacionados