diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
index f90a0c4658..a49616e543 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
@@ -51,6 +51,11 @@
Width="200"
Margin="0,0,0,8"
FilterMode="None"/>
+
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
index f9d6a72a3a..574cc79a7d 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
@@ -92,13 +92,28 @@ namespace ControlCatalog.Pages
}
public StateData[] States { get; private set; }
+ private LinkedList[] BuildAllSentences()
+ {
+ return new string[]
+ {
+ "Hello world",
+ "No this is Patrick",
+ "Never gonna give you up",
+ "How does one patch KDE2 under FreeBSD"
+ }
+ .Select(x => new LinkedList(x.Split(' ')))
+ .ToArray();
+ }
+ public LinkedList[] Sentences { get; private set; }
+
public AutoCompleteBoxPage()
{
this.InitializeComponent();
States = BuildAllStates();
+ Sentences = BuildAllSentences();
- foreach (AutoCompleteBox box in GetAllAutoCompleteBox())
+ foreach (AutoCompleteBox box in GetAllAutoCompleteBox().Where(x => x.Name != "CustomAutocompleteBox"))
{
box.Items = States;
}
@@ -116,6 +131,11 @@ namespace ControlCatalog.Pages
var asyncBox = this.FindControl("AsyncBox");
asyncBox.AsyncPopulator = PopulateAsync;
+
+ var customAutocompleteBox = this.FindControl("CustomAutocompleteBox");
+ customAutocompleteBox.Items = Sentences.SelectMany(x => x);
+ customAutocompleteBox.TextFilter = LastWordContains;
+ customAutocompleteBox.TextSelector = AppendWord;
}
private IEnumerable GetAllAutoCompleteBox()
{
@@ -137,6 +157,42 @@ namespace ControlCatalog.Pages
.ToList();
}
+ private bool LastWordContains(string searchText, string item)
+ {
+ var words = searchText.Split(' ');
+ var options = Sentences.Select(x => x.First).ToArray();
+ for (var i = 0; i < words.Length; ++i)
+ {
+ var word = words[i];
+ for (var j = 0; j < options.Length; ++j)
+ {
+ var option = options[j];
+ if (option == null)
+ continue;
+
+ if (i == words.Length - 1)
+ {
+ options[j] = option.Value.ToLower().Contains(word.ToLower()) ? option : null;
+ }
+ else
+ {
+ options[j] = option.Value.Equals(word, StringComparison.InvariantCultureIgnoreCase) ? option.Next : null;
+ }
+ }
+ }
+
+ return options.Any(x => x != null && x.Value == item);
+ }
+ private string AppendWord(string text, string item)
+ {
+ string[] parts = text.Split(' ');
+ if (parts.Length == 0)
+ return item;
+
+ parts[parts.Length - 1] = item;
+ return string.Join(" ", parts);
+ }
+
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs
index 6bbb4f0b75..bfd633c947 100644
--- a/src/Avalonia.Controls/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox.cs
@@ -227,6 +227,27 @@ namespace Avalonia.Controls
Custom = 13,
}
+ ///
+ /// Represents the selector used by the
+ /// control to
+ /// determine how the specified text should be modified with an item.
+ ///
+ ///
+ /// Modified text that will be used by the
+ /// .
+ ///
+ /// The string used as the basis for filtering.
+ ///
+ /// The selected item that should be combined with the
+ /// parameter.
+ ///
+ ///
+ /// The type used for filtering the
+ /// .
+ /// This type can be either a string or an object.
+ ///
+ public delegate string AutoCompleteSelector(string search, T item);
+
///
/// Represents a control that provides a text box for user input and a
/// drop-down that contains possible matches based on the input in the text
@@ -364,6 +385,9 @@ namespace Avalonia.Controls
private AutoCompleteFilterPredicate