我有一个快速查找文本框。我想过滤包含 quickFind 字符串的记录的集合。
如何延迟搜索,直到用户停止输入 2 秒?
这是完成整个事情的 ReactiveUI 方式(在 2 秒延迟后过滤项目):
// These are defined in your ViewModel class as settable Properties
string FilterText;
ReactiveList<Record> ListOfRecords;
IReactiveDerivedList<Record> FilteredRecords;
// This is in your ViewModel constructor
FilteredRecords = ListOfRecords.CreateDerivedCollection(
x => !String.IsNullOrWhiteSpace(FilterText) ? recordContainsString(FilterText) : true,
x => x.Id,
this.WhenAnyValue(x => x.FilterText).Throttle(TimeSpan.FromSeconds(2.0));
如果您要做的只是找出属性何时更改但在空闲时间之后,它是:
this.WhenAnyValue(x => x.SomeProperty)
.Throttle(TimeSpan.FromSeconds(2.0), RxApp.MainThreadScheduler)
.Subscribe(x => Console.WriteLine("The item is " + x);
我喜欢 Timer and Lock 示例,因为它显示了 ReactiveUI 是多么容易:)
下面是一个我希望对你有用的课程。包括底部显示的示例用法。
public class EventDelayer
{
/// <summary>
/// Contains info on an individual event that was queued;
/// </summary>
public class DelayedEventInfo
{
private readonly object _sender;
private readonly EventArgs _eventArgs;
private readonly DateTime _eventTime;
public DelayedEventInfo(object sender, EventArgs eventArgs, DateTime eventTime)
{
_sender = sender;
_eventArgs = eventArgs;
_eventTime = eventTime;
}
public object Sender { get { return _sender; } }
public EventArgs EventArgs { get { return _eventArgs; } }
public DateTime EventTime { get { return _eventTime; } }
}
/// <summary>
/// contains a list of
/// </summary>
public class DelayedEventArgs : EventArgs, IEnumerable<DelayedEventInfo>
{
private readonly List<DelayedEventInfo> _eventInfos;
public DelayedEventArgs(IEnumerable<DelayedEventInfo> eventInfos)
{
_eventInfos = new List<DelayedEventInfo>(eventInfos);
}
public IEnumerator<DelayedEventInfo> GetEnumerator()
{
return _eventInfos.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _eventInfos.GetEnumerator();
}
}
private readonly List<DelayedEventInfo> _infoList = new List<DelayedEventInfo>();
private readonly TimeSpan _delayTime;
private readonly object _lock = new object();
private System.Threading.Timer _timer;
public event EventHandler<DelayedEventArgs> DelayedEvent;
public EventDelayer(TimeSpan delayTime)
{
_delayTime = delayTime;
}
/// <summary>
/// call to 'enqueue' an event.
/// </summary>
public void Enqueue(object sender, EventArgs args)
{
lock (_lock)
{
_infoList.Add(new DelayedEventInfo(sender, args, DateTime.Now));
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
_timer = new System.Threading.Timer(ThreadProc, this, _delayTime, TimeSpan.FromMilliseconds(-1));
}
}
/// <summary>
/// raises the event.
/// </summary>
private void HandleTimer()
{
lock (_lock)
{
var ev = this.DelayedEvent;
if (ev != null)
{
DelayedEventArgs args = new DelayedEventArgs(_infoList);
Invoke(()=> ev(this, args));
}
_infoList.Clear();
}
}
private static void ThreadProc(Object stateInfo)
{
EventDelayer thisObj = (EventDelayer)stateInfo;
thisObj.HandleTimer();
}
private static Lazy<System.Windows.Threading.Dispatcher> _dispatchObject = new Lazy<System.Windows.Threading.Dispatcher>(() =>
{
if (Application.Current != null)
{
return Application.Current.Dispatcher;
}
else
{
return null;
}
});
public static void Invoke(Action action)
{
if (_dispatchObject.Value == null || _dispatchObject.Value.CheckAccess())
{
action();
}
else
{
_dispatchObject.Value.Invoke(action);
}
}
}
private class ExampleUsage
{
/// <summary>
/// shows how to create a event delayer and use it to listen to the events from a text box and call if no further changes for 2 seconds.
/// </summary>
private static void ShowUsage(System.Windows.Controls.TextBox textBox)
{
EventDelayer eventDelayer = new EventDelayer(TimeSpan.FromSeconds(2));
textBox.TextChanged += eventDelayer.Enqueue;
eventDelayer.DelayedEvent += eventDelayer_DelayedEvent;
}
/// <summary>
/// redo search here. if required you can access the event args originally raised from the textbox through the event args of this method
/// </summary>
static void eventDelayer_DelayedEvent(object sender, EventDelayer.DelayedEventArgs e)
{
foreach (var eventInfo in e)
{
var originalSender = eventInfo.Sender;
var args = eventInfo.EventArgs;
var timeInitiallyCalled = eventInfo.EventTime;
}
}
}
将文本框文本绑定到字符串,然后在绑定中设置延迟
<TextBox>
<TextBox.Text>
<Binding Path="searchText" UpdateSourceTrigger="PropertyChanged" Delay="2000" />
</TextBox.Text>
</TextBox>