WPF TextBox防抖动实现
方案 A:手写一个 20 行不到的防抖器
添加防抖动类Debouncer.cs
using System;
using System.Timers;
using System.Windows.Threading; // 如果是 WPF 需要回到 UI 线程
public class Debouncer
{
private readonly Timer _timer;
private readonly Action _action;
public Debouncer(TimeSpan dueTime, Action action)
{
_action = action;
_timer = new Timer
{
AutoReset = false,
Interval = dueTime.TotalMilliseconds
};
_timer.Elapsed += (_, __) =>
{
// 回到 UI 线程(WPF 场景)
Dispatcher.CurrentDispatcher.Invoke(_action);
};
}
public void Action()
{
_timer.Stop();
_timer.Start();
}
public void Cancel() => _timer.Stop();
}
在ViewModel中使用
public class SearchViewModel : Screen
{
private readonly Debouncer _searchDebouncer;
private string _searchKeyWordText;
public string SearchKeyWordText
{
get => _searchKeyWordText;
set
{
if (SetAndNotify(ref _searchKeyWordText, value))
_searchDebouncer.Action(); // 每次输入都会重置防抖计时器
}
}
public SearchViewModel()
{
_searchDebouncer = new Debouncer(
dueTime: TimeSpan.FromMilliseconds(400),
action: DoSearch);
}
private void DoSearch()
{
// 真正的搜索逻辑
Debug.WriteLine($"搜索关键词:{SearchKeyWordText}");
}
protected override void OnClose()
{
_searchDebouncer.Cancel(); // 防止内存泄漏
base.OnClose();
}
}
方案 B:使用 System.Reactive.Linq(需要 NuGet)
如果你愿意多引一个包,代码会更短,功能也更强:
安装
Install-Package System.Reactive.Linq
ViewModel 代码:
using System.Reactive.Linq;
using System.Reactive.Disposables;
public class SearchViewModel : Screen
{
private readonly IDisposable _subscription;
private string _searchKeyWordText;
public string SearchKeyWordText
{
get => _searchKeyWordText;
set => SetAndNotify(ref _searchKeyWordText, value);
}
public SearchViewModel()
{
_subscription = this.WhenAnyValue(x => x.SearchKeyWordText)
.Throttle(TimeSpan.FromMilliseconds(400))
.ObserveOnDispatcher() // 回到 UI 线程
.Subscribe(DoSearch);
}
private void DoSearch(string keyword)
{
Debug.WriteLine($"Rx 搜索关键词:{keyword}");
}
protected override void OnClose()
{
_subscription?.Dispose();
base.OnClose();
}
}
浙公网安备 33010602011771号