Entry control that makes suggestions to users as they type.
NOTE: This control is based on the awesome dotMortem/XamarinFormsControls/AutoSuggestBox. with some simplifications and modifications of my own.
Add NuGet Package to your project:
dotnet add package zoft.MauiExtensions.Controls.AutoCompleteEntry`
You can find the nuget package here zoft.MauiExtensions.Controls.AutoCompleteEntry
Initialize the library in your MauiProgram.cs
file:
using CommunityToolkit.Maui;
using zoft.MauiExtensions.Controls;
namespace AutoCompleteEntry.Sample
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.UseZoftAutoCompleteEntry()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
return builder.Build();
}
}
}
The filtering of results, happens as the user types and you'll only need to respond to 2 actions:
Binding based
TextChangedCommand
: Triggered every time the user changes the text. Receives the current text as parameter;SelectedSuggestion
: Holds the currently selected option;
Event based
TextChanged
: Event raised every time the user changes the text. The current text is part of the event arguments;SuggestionChosen
: Event raised every time a suggestion is chosen. The selected option is part of the event arguments;
In order to make use of the control within XAML you can use this namespace:
xmlns:zoft="http://zoft.MauiExtensions/Controls"
<ContentPage ...
xmlns:zoft="http://zoft.MauiExtensions/Controls"
...>
<zoft:AutoCompleteEntry Placeholder="Search for a country or group"
ItemsSource="{Binding FilteredList}"
TextMemberPath="Country"
DisplayMemberPath="Country"
TextChangedCommand="{Binding TextChangedCommand}"
CursorPosition="{Binding CursorPosition, Mode=TwoWay}"
SelectedSuggestion="{Binding SelectedItem}"
Completed="AutoCompleteEntry_Completed"
ClearButtonVisibility="Never"
HeightRequest="50"/>
</ContentPage>
internal partial class ListItem : ObservableObject
{
[ObservableProperty]
public string _group;
[ObservableProperty]
public string _country;
}
internal partial class SampleViewModel : CoreViewModel
{
private readonly List<ListItem> Teams = new List<ListItem>() { ... };
[ObservableProperty]
private ObservableCollection<ListItem> _filteredList;
[ObservableProperty]
private ListItem _selectedItem;
[ObservableProperty]
private int _cursorPosition;
public SampleViewModel()
{
FilteredList = new(Teams);
SelectedItem = null;
}
private void FilterList(string filter)
{
SelectedItem = null;
FilteredList.Clear();
FilteredList.AddRange(Teams.Where(t => t.Group.Contains(filter, StringComparison.CurrentCultureIgnoreCase) ||
t.Country.Contains(filter, StringComparison.CurrentCultureIgnoreCase)));
}
[RelayCommand]
private void TextChanged(string text)
{
FilterList(text);
}
}
<ContentPage ...
xmlns:zoft="http://zoft.MauiExtensions/Controls"
...>
<zoft:AutoCompleteEntry Placeholder="Search for a country or group"
ItemsSource="{Binding FilteredList}"
TextMemberPath="Country"
DisplayMemberPath="Country"
TextChanged="AutoCompleteEntry_TextChanged"
CursorPosition="{Binding CursorPosition, Mode=TwoWay}"
CursorPositionChanged="AutoCompleteEntry_CursorPositionChanged"
SuggestionChosen="AutoCompleteEntry_SuggestionChosen"
Completed="AutoCompleteEntry_Completed"
ClearButtonVisibility="WhileEditing"
HeightRequest="50"/>
</ContentPage>
private void AutoCompleteEntry_TextChanged(object sender, zoft.MauiExtensions.Controls.AutoCompleteEntryTextChangedEventArgs e)
{
// Filter only when the user is typing
if (e.Reason == zoft.MauiExtensions.Controls.AutoCompleteEntryTextChangeReason.UserInput)
{
//Filter the ItemsSource, based on text
ViewModel.FilterList((sender as zoft.MauiExtensions.Controls.AutoCompleteEntry).Text);
}
}
private void AutoCompleteEntry_SuggestionChosen(object sender, zoft.MauiExtensions.Controls.AutoCompleteEntrySuggestionChosenEventArgs e)
{
//Set the SelectedItem provided by the event arguments
ViewModel.SelectedItem = e.SelectedItem as ListItem;
}