0

私はquickFind TextBoxを持っています。quickFind 文字列を含むレコードのコレクションをフィルター処理したいと考えています。

ユーザーが入力を 2 秒間停止するまで検索を遅らせるにはどうすればよいですか?

4

3 に答える 3

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

ReactiveUI がいかに簡単かを示しているので、Timer と Lock の例が気に入っています :)

于 2013-11-08T06:18:53.417 に答える
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;
        }
    }
}
于 2013-11-05T21:41:57.317 に答える