205 lines
6.9 KiB
C#
205 lines
6.9 KiB
C#
using System;
|
|
using System.Timers;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Threading;
|
|
|
|
namespace FasdDesktopUi.Basics.UserControls
|
|
{
|
|
public partial class SearchBar : UserControl
|
|
{
|
|
private readonly Timer _searchTimer = new Timer();
|
|
|
|
#region Dependency Properties
|
|
|
|
public static readonly DependencyProperty SearchButtonSizeProperty =
|
|
DependencyProperty.Register(nameof(SearchButtonSize), typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
|
|
|
|
public double SearchButtonSize
|
|
{
|
|
get => (double)GetValue(SearchButtonSizeProperty);
|
|
set => SetValue(SearchButtonSizeProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty CloseButtonSizeProperty =
|
|
DependencyProperty.Register(nameof(CloseButtonSize), typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
|
|
|
|
public double CloseButtonSize
|
|
{
|
|
get => (double)GetValue(CloseButtonSizeProperty);
|
|
set => SetValue(CloseButtonSizeProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty ShowCloseButtonProperty =
|
|
DependencyProperty.Register(nameof(ShowCloseButton), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
|
|
|
|
public bool ShowCloseButton
|
|
{
|
|
get => (bool)GetValue(ShowCloseButtonProperty);
|
|
set => SetValue(ShowCloseButtonProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty ShowSearchButtonProperty =
|
|
DependencyProperty.Register(nameof(ShowSearchButton), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
|
|
|
|
public bool ShowSearchButton
|
|
{
|
|
get => (bool)GetValue(ShowSearchButtonProperty);
|
|
set => SetValue(ShowSearchButtonProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty PlaceholderTextProperty =
|
|
DependencyProperty.Register(nameof(PlaceholderText), typeof(string), typeof(SearchBar), new PropertyMetadata(string.Empty));
|
|
|
|
public string PlaceholderText
|
|
{
|
|
get => (string)GetValue(PlaceholderTextProperty);
|
|
set => SetValue(PlaceholderTextProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty DebounceIntervalProperty =
|
|
DependencyProperty.Register(nameof(DebounceInterval), typeof(TimeSpan), typeof(SearchBar),
|
|
new PropertyMetadata(TimeSpan.FromMilliseconds(250), OnDebounceIntervalChanged));
|
|
|
|
public TimeSpan DebounceInterval
|
|
{
|
|
get => (TimeSpan)GetValue(DebounceIntervalProperty);
|
|
set => SetValue(DebounceIntervalProperty, value);
|
|
}
|
|
|
|
private static void OnDebounceIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
TimeSpan interval = (TimeSpan)e.NewValue;
|
|
((SearchBar)d)._searchTimer.Interval = Math.Max(interval.TotalMilliseconds, 10);
|
|
}
|
|
|
|
public static readonly DependencyProperty IsInputEnabledProperty =
|
|
DependencyProperty.Register(nameof(IsInputEnabled), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
|
|
|
|
public bool IsInputEnabled
|
|
{
|
|
get => (bool)GetValue(IsInputEnabledProperty);
|
|
set => SetValue(IsInputEnabledProperty, value);
|
|
}
|
|
|
|
public SolidColorBrush SearchBackground
|
|
{
|
|
get { return (SolidColorBrush)GetValue(SearchBackgroundProperty); }
|
|
set { SetValue(SearchBackgroundProperty, value); }
|
|
}
|
|
|
|
public static readonly DependencyProperty SearchBackgroundProperty =
|
|
DependencyProperty.Register(nameof(SearchBackground), typeof(SolidColorBrush), typeof(SearchBar), new PropertyMetadata(null));
|
|
|
|
#endregion
|
|
|
|
#region SearchValue
|
|
|
|
private string _searchValue = null;
|
|
public string SearchValue
|
|
{
|
|
get => _searchValue;
|
|
set
|
|
{
|
|
if (value != _searchValue)
|
|
{
|
|
_searchValue = value;
|
|
if (IsInputEnabled)
|
|
HandleSearchValueChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
public event EventHandler<string> SearchValueChanged;
|
|
|
|
public static readonly RoutedEvent CancelledSearchEvent =
|
|
EventManager.RegisterRoutedEvent(nameof(CancelledSearch), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SearchBar));
|
|
|
|
public event RoutedEventHandler CancelledSearch
|
|
{
|
|
add => AddHandler(CancelledSearchEvent, value);
|
|
remove => RemoveHandler(CancelledSearchEvent, value);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public SearchBar()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
SearchTextBox.Text = null;
|
|
}
|
|
|
|
public void SetSearchText(string search)
|
|
{
|
|
SearchTextBox.Text = search;
|
|
SearchTextBox.CaretIndex = search?.Length ?? 0;
|
|
SearchTextBox.Focus();
|
|
Keyboard.Focus(SearchTextBox);
|
|
}
|
|
|
|
public void FocusInput()
|
|
{
|
|
SearchTextBox.Focus();
|
|
Keyboard.Focus(SearchTextBox);
|
|
}
|
|
|
|
internal void SetSpinnerVisibility(Visibility visibility)
|
|
{
|
|
Dispatcher.Invoke(() => SearchSpinner.Visibility = visibility);
|
|
}
|
|
|
|
private void HandleSearchValueChanged()
|
|
{
|
|
if (_searchTimer.Enabled)
|
|
_searchTimer.Stop();
|
|
|
|
_searchTimer.Start();
|
|
}
|
|
|
|
private void SearchTimerTick(object sender, EventArgs e)
|
|
{
|
|
_searchTimer.Stop();
|
|
SearchValueChanged?.Invoke(this, SearchValue);
|
|
}
|
|
|
|
private void SearchButton_Click(object sender, InputEventArgs e)
|
|
{
|
|
SearchTextBox.Focus();
|
|
}
|
|
|
|
private void CloseButton_Click(object sender, InputEventArgs e)
|
|
{
|
|
RaiseEvent(new RoutedEventArgs(CancelledSearchEvent));
|
|
}
|
|
|
|
private void SearchBar_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
_searchTimer.Stop();
|
|
_searchTimer.Interval = Math.Max(DebounceInterval.TotalMilliseconds, 10);
|
|
_searchTimer.Elapsed += SearchTimerTick;
|
|
BackgroundBorder.CornerRadius = new CornerRadius(BackgroundBorder.ActualHeight / 2.0);
|
|
}
|
|
|
|
internal void ActivateManualSearch()
|
|
{
|
|
Search.Clear();
|
|
Search.IsInputEnabled = true;
|
|
|
|
Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
Search.FocusInput();
|
|
}), DispatcherPriority.Input);
|
|
}
|
|
}
|
|
}
|