WPF TextBox搜索

时间:2013-11-05 20:34:03

标签: c# wpf reactiveui

我有一个quickFind TextBox。我想过滤包含quickFind字符串的记录的集合。

如果用户停止输入2秒钟,我该如何延迟搜索?

3 个答案:

答案 0 :(得分: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和Lock示例,因为它显示了ReactiveUI更容易:)

答案 1 :(得分:0)

下面是一个我希望能帮到你的课程。包括底部显示的样本用法。

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;
        }
    }
}

答案 2 :(得分:0)

将文本框文本绑定到字符串,然后在绑定中设置延迟

<TextBox>
    <TextBox.Text>
        <Binding Path="searchText" UpdateSourceTrigger="PropertyChanged" Delay="2000" />
    </TextBox.Text>
</TextBox>