Skip to content

Commit

Permalink
Merge pull request #7594 from pr8x/text-search-property
Browse files Browse the repository at this point in the history
Implement `TextSearch.Text`
  • Loading branch information
maxkatz6 authored Feb 15, 2022
2 parents 86e62cf + 33d75c4 commit 53a363e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,23 @@ protected override void OnTextInput(TextInputEventArgs e)

_textSearchTerm += e.Text;

bool match(ItemContainerInfo info) =>
info.ContainerControl is IContentControl control &&
control.Content?.ToString()?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true;
bool Match(ItemContainerInfo info)
{
if (info.ContainerControl.IsSet(TextSearch.TextProperty))
{
var searchText = info.ContainerControl.GetValue(TextSearch.TextProperty);

var info = ItemContainerGenerator?.Containers.FirstOrDefault(match);
if (searchText?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}

return info.ContainerControl is IContentControl control &&
control.Content?.ToString()?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true;
}

var info = ItemContainerGenerator?.Containers.FirstOrDefault(Match);

if (info != null)
{
Expand Down
37 changes: 37 additions & 0 deletions src/Avalonia.Controls/Primitives/TextSearch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Avalonia.Interactivity;

namespace Avalonia.Controls.Primitives
{
/// <summary>
/// Allows to customize text searching in <see cref="SelectingItemsControl"/>.
/// </summary>
public static class TextSearch
{
/// <summary>
/// Defines the Text attached property.
/// This text will be considered during text search in <see cref="SelectingItemsControl"/> (such as <see cref="ComboBox"/>)
/// </summary>
public static readonly AttachedProperty<string> TextProperty
= AvaloniaProperty.RegisterAttached<Interactive, string>("Text", typeof(TextSearch));

/// <summary>
/// Sets the <see cref="TextProperty"/> for a control.
/// </summary>
/// <param name="control">The control</param>
/// <param name="text">The search text to set</param>
public static void SetText(Control control, string text)
{
control.SetValue(TextProperty, text);
}

/// <summary>
/// Gets the <see cref="TextProperty"/> of a control.
/// </summary>
/// <param name="control">The control</param>
/// <returns>The property value</returns>
public static string GetText(Control control)
{
return control.GetValue(TextProperty);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Disposables;
using Avalonia.Collections;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
Expand All @@ -13,7 +15,9 @@
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Data;
using Avalonia.Platform;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Moq;
using Xunit;
Expand Down Expand Up @@ -1895,6 +1899,54 @@ public void Handles_Removing_Last_Item_In_Controls_With_Bound_SelectedItem()
Assert.Equal(1, carouselRaised);
}

[Fact]
public void Setting_IsTextSearchEnabled_Enables_Or_Disables_Text_Search()
{
var pti = Mock.Of<IPlatformThreadingInterface>(x => x.CurrentThreadIsLoopThread == true);

Mock.Get(pti)
.Setup(v => v.StartTimer(It.IsAny<DispatcherPriority>(), It.IsAny<TimeSpan>(), It.IsAny<Action>()))
.Returns(Disposable.Empty);

using (UnitTestApplication.Start(TestServices.StyledWindow.With(threadingInterface: pti)))
{
var items = new[]
{
new Item { [TextSearch.TextProperty] = "Foo" },
new Item { [TextSearch.TextProperty] = "Bar" }
};

var target = new SelectingItemsControl
{
Items = items,
Template = Template(),
IsTextSearchEnabled = false
};

Prepare(target);

target.RaiseEvent(new TextInputEventArgs
{
RoutedEvent = InputElement.TextInputEvent,
Device = KeyboardDevice.Instance,
Text = "Foo"
});

Assert.Null(target.SelectedItem);

target.IsTextSearchEnabled = true;

target.RaiseEvent(new TextInputEventArgs
{
RoutedEvent = InputElement.TextInputEvent,
Device = KeyboardDevice.Instance,
Text = "Foo"
});

Assert.Equal(items[0], target.SelectedItem);
}
}

private static void Prepare(SelectingItemsControl target)
{
var root = new TestRoot
Expand Down

0 comments on commit 53a363e

Please sign in to comment.