A powerful AutoCompleteEntry control for .NET MAUI that makes suggestions to users as they type. This control provides rich customization options, data templating support, and works consistently across all supported platforms.
- β¨ Features
- π Getting Started
- π Properties Reference
- π― Basic Usage
- π‘ Usage Examples
- ποΈ Platform Support Matrix
- π± Platform Screenshots
- π¨ Advanced Customization
- π Troubleshooting
- π Support
- π€ Contributing
- π License
- π Acknowledgments
- π Real-time filtering as the user types
- π¨ Custom item templates for rich suggestion display
- π± Cross-platform support (iOS, Android, Windows, MacCatalyst)
- π Flexible data binding with command and event-based approaches
- βοΈ Highly customizable appearance and behavior
- π― Full Entry compatibility - inherits all Entry properties and behaviors
Add the NuGet package to your project:
dotnet add package zoft.MauiExtensions.Controls.AutoCompleteEntry
π¦ View on NuGet
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() // π Add this line
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
return builder.Build();
}
}
}
Add this namespace to your XAML files:
xmlns:zoft="http://zoft.MauiExtensions/Controls"
Property | Type | Default | Description |
---|---|---|---|
ItemsSource |
IList |
null |
Collection of suggestion items to display |
SelectedSuggestion |
object |
null |
Currently selected suggestion item (two-way binding) |
DisplayMemberPath |
string |
"" |
Property path for displaying items in the suggestion list |
TextMemberPath |
string |
"" |
Property path for the text value when an item is selected |
ItemTemplate |
DataTemplate |
null |
Custom template for rendering suggestion items |
IsSuggestionListOpen |
bool |
false |
Controls whether the suggestion dropdown is open |
UpdateTextOnSelect |
bool |
true |
Whether selecting an item updates the text field |
ShowBottomBorder |
bool |
true |
Controls the visibility of the bottom border |
TextChangedCommand |
ICommand |
null |
Command executed when text changes (receives text as parameter) |
AutoCompleteEntry inherits from Entry
, so all standard Entry properties are available:
Property | Description |
---|---|
Text |
The current text value |
Placeholder |
Placeholder text when empty |
PlaceholderColor |
Color of the placeholder text |
TextColor |
Color of the input text |
FontSize , FontFamily , FontAttributes |
Text formatting |
IsReadOnly |
Whether the text can be edited |
MaxLength |
Maximum character length |
CursorPosition |
Current cursor position |
ClearButtonVisibility |
When to show the clear button |
HorizontalTextAlignment , VerticalTextAlignment |
Text alignment |
CharacterSpacing |
Spacing between characters |
IsTextPredictionEnabled |
Enable/disable text prediction |
ReturnType |
Keyboard return key type |
Event | EventArgs | Description |
---|---|---|
TextChanged |
AutoCompleteEntryTextChangedEventArgs |
Fired when text changes (includes change reason) |
SuggestionChosen |
AutoCompleteEntrySuggestionChosenEventArgs |
Fired when a suggestion is selected |
CursorPositionChanged |
AutoCompleteEntryCursorPositionChangedEventArgs |
Fired when cursor position changes |
Plus all inherited Entry events: Completed
, Focused
, Unfocused
The filtering of results happens as the user types. You can respond to text changes using either:
π Binding-Based Approach (Recommended)
- Use
TextChangedCommand
for filtering logic - Bind
SelectedSuggestion
for the selected item
β‘ Event-Based Approach
- Handle
TextChanged
event for filtering - Handle
SuggestionChosen
event for selection
<zoft:AutoCompleteEntry
Placeholder="Search for a country or group"
ItemsSource="{Binding FilteredList}"
TextMemberPath="Country"
DisplayMemberPath="Country"
TextChangedCommand="{Binding TextChangedCommand}"
SelectedSuggestion="{Binding SelectedItem}"
HeightRequest="50" />
ViewModel Implementation:
public partial class SampleViewModel : ObservableObject
{
private readonly List<CountryItem> _allCountries = new()
{
new CountryItem { Group = "Group A", Country = "Ecuador" },
new CountryItem { Group = "Group B", Country = "Netherlands" },
// ... more items
};
[ObservableProperty]
private ObservableCollection<CountryItem> _filteredList;
[ObservableProperty]
private CountryItem _selectedItem;
[ObservableProperty]
private int _cursorPosition;
public SampleViewModel()
{
FilteredList = new(_allCountries);
}
[RelayCommand]
private void TextChanged(string text)
{
FilteredList.Clear();
var filtered = _allCountries.Where(item =>
item.Country.Contains(text, StringComparison.OrdinalIgnoreCase) ||
item.Group.Contains(text, StringComparison.OrdinalIgnoreCase));
foreach (var item in filtered)
FilteredList.Add(item);
}
}
public class CountryItem
{
public string Group { get; set; }
public string Country { get; set; }
}
<zoft:AutoCompleteEntry
Placeholder="Search countries with custom display"
ItemsSource="{Binding FilteredList}"
TextMemberPath="Country"
DisplayMemberPath="Country"
TextChangedCommand="{Binding TextChangedCommand}"
SelectedSuggestion="{Binding SelectedItem}"
ShowBottomBorder="{Binding ShowBottomBorder}"
HeightRequest="50">
<!-- π¨ Custom item template for rich display -->
<zoft:AutoCompleteEntry.ItemTemplate>
<DataTemplate x:DataType="vm:CountryItem">
<Grid ColumnDefinitions="Auto,*,Auto"
Padding="12,8"
HeightRequest="60">
<!-- Flag or Group Indicator -->
<Border Grid.Column="0"
BackgroundColor="{Binding GroupColor}"
WidthRequest="4"
HeightRequest="40"
StrokeShape="RoundRectangle 2" />
<!-- Country Details -->
<StackLayout Grid.Column="1"
Margin="12,0">
<Label Text="{Binding Country}"
FontSize="16"
FontAttributes="Bold"
TextColor="Black" />
<Label Text="{Binding Group}"
FontSize="12"
TextColor="Gray" />
</StackLayout>
<!-- Population or other info -->
<Label Grid.Column="2"
Text="{Binding Population, StringFormat='{0:N0}'}"
FontSize="12"
TextColor="DarkGray"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</zoft:AutoCompleteEntry.ItemTemplate>
</zoft:AutoCompleteEntry>
<zoft:AutoCompleteEntry
Placeholder="Search for a country or group"
ItemsSource="{Binding FilteredList}"
TextMemberPath="Country"
DisplayMemberPath="Country"
TextChanged="AutoCompleteEntry_TextChanged"
SuggestionChosen="AutoCompleteEntry_SuggestionChosen"
CursorPositionChanged="AutoCompleteEntry_CursorPositionChanged"
ClearButtonVisibility="WhileEditing"
HeightRequest="50" />
Code-Behind Implementation:
private void AutoCompleteEntry_TextChanged(object sender, AutoCompleteEntryTextChangedEventArgs e)
{
// Only filter when the user is actually typing
if (e.Reason == AutoCompleteEntryTextChangeReason.UserInput)
{
var autoComplete = sender as AutoCompleteEntry;
ViewModel.FilterList(autoComplete.Text);
}
}
private void AutoCompleteEntry_SuggestionChosen(object sender, AutoCompleteEntrySuggestionChosenEventArgs e)
{
// Handle the selected suggestion
if (e.SelectedItem is CountryItem selectedCountry)
{
ViewModel.SelectedItem = selectedCountry;
// Perform additional actions like navigation or validation
}
}
private void AutoCompleteEntry_CursorPositionChanged(object sender, AutoCompleteEntryCursorPositionChangedEventArgs e)
{
// Track cursor position for analytics or custom behavior
Console.WriteLine($"Cursor moved to position: {e.NewCursorPosition}");
}
// Programmatically open/close the suggestion list
autoCompleteEntry.IsSuggestionListOpen = true;
// Control text updates on selection
autoCompleteEntry.UpdateTextOnSelect = false; // Keep original text when selecting
// Customize appearance
autoCompleteEntry.ShowBottomBorder = false; // Remove bottom border
autoCompleteEntry.ClearButtonVisibility = ClearButtonVisibility.WhileEditing;
// Handle selection programmatically
autoCompleteEntry.SelectedSuggestion = mySelectedItem;
Feature | Windows | Android | iOS | MacCatalyst | Notes |
---|---|---|---|---|---|
Core Functionality | |||||
Text Input & Filtering | β | β | β | β | Full support |
ItemsSource Binding | β | β | β | β | Full support |
Selection Events | β | β | β | β | Full support |
Appearance & Styling | |||||
ItemTemplate | β | β | β | β | Windows: Planned for future release |
ShowBottomBorder | β | β | β | β | Windows: Planned for future release |
Text Styling | β | β | β | β | Fonts, colors, alignment |
Behavior | |||||
UpdateTextOnSelect | β | β | β | β | Full support |
IsSuggestionListOpen | β | β | β | β | Full support |
CursorPosition | β | β | β | β | Full support |
Entry Features | |||||
ClearButtonVisibility | β | β | β | β | Full support |
Placeholder | β | β | β | β | Full support |
IsReadOnly | β | β | β | β | Full support |
MaxLength | β | β | β | β | Full support |
- β Fully Supported - Feature works as expected
- β Not Implemented - Feature exists in API but not yet implemented on this platform
β οΈ Limited Support - Feature works with some limitations
While the AutoCompleteEntry works great on Windows, some advanced styling features are still in development:
- ItemTemplate: Currently displays items using their string representation. Custom templates are planned for a future release.
- ShowBottomBorder: This styling option doesn't affect the Windows presentation currently.
All core functionality including filtering, selection, and data binding works perfectly on Windows.
Create rich, interactive suggestion lists with custom DataTemplates:
<zoft:AutoCompleteEntry.ItemTemplate>
<DataTemplate x:DataType="models:Product">
<Grid ColumnDefinitions="60,*,Auto"
RowDefinitions="Auto,Auto"
Padding="16,12">
<!-- Product Image -->
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
WidthRequest="50"
HeightRequest="50"
Aspect="AspectFill" />
<!-- Product Info -->
<Label Grid.Column="1"
Text="{Binding Name}"
FontSize="16"
FontAttributes="Bold" />
<Label Grid.Column="1" Grid.Row="1"
Text="{Binding Category}"
FontSize="12"
TextColor="Gray" />
<!-- Price -->
<Label Grid.Column="2" Grid.RowSpan="2"
Text="{Binding Price, StringFormat='${0:F2}'}"
FontSize="14"
FontAttributes="Bold"
VerticalOptions="Center"
HorizontalOptions="End" />
</Grid>
</DataTemplate>
</zoft:AutoCompleteEntry.ItemTemplate>
<Style x:Key="CustomAutoCompleteStyle" TargetType="zoft:AutoCompleteEntry">
<Setter Property="BackgroundColor" Value="{DynamicResource SurfaceColor}" />
<Setter Property="TextColor" Value="{DynamicResource OnSurfaceColor}" />
<Setter Property="PlaceholderColor" Value="{DynamicResource OnSurfaceVariantColor}" />
<Setter Property="FontSize" Value="16" />
<Setter Property="HeightRequest" Value="56" />
<Setter Property="Margin" Value="16,8" />
<Setter Property="ShowBottomBorder" Value="True" />
</Style>
- Efficient Filtering: Use proper indexing and async operations for large datasets
- Template Complexity: Keep ItemTemplates lightweight for smooth scrolling
- Data Virtualization: Consider implementing virtualization for very large lists
- Debouncing: Implement debouncing in your TextChangedCommand for better UX
// Example: Debounced filtering
private CancellationTokenSource _filterCancellation;
[RelayCommand]
private async Task TextChanged(string text)
{
_filterCancellation?.Cancel();
_filterCancellation = new CancellationTokenSource();
try
{
await Task.Delay(300, _filterCancellation.Token); // Debounce
await FilterItemsAsync(text);
}
catch (TaskCanceledException)
{
// Filtering was cancelled by newer input
}
}
Issue: Suggestions not appearing
- β
Ensure
ItemsSource
is properly bound and contains data - β
Check
DisplayMemberPath
matches your data model properties - β Verify the control has sufficient height to display suggestions
Issue: Selection not working
- β
Confirm
SelectedSuggestion
binding is two-way - β
Check
TextMemberPath
property is correctly set - β
Ensure the selected item exists in the current
ItemsSource
Issue: Custom templates not rendering (Windows)
β οΈ ItemTemplate is not yet implemented on Windows platform- β Use DisplayMemberPath for basic text display on Windows
Issue: Performance issues with large datasets
- β Implement efficient filtering logic
- β Use proper async/await patterns
- β Consider pagination or virtual scrolling
If you find this project helpful, please consider supporting its development:
Your support helps maintain and improve this project for the entire .NET MAUI community. Thank you! π
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License - see the LICENSE.md file for details.
- Inspired by platform-native autocomplete controls
- Built with β€οΈ for the .NET MAUI community