4

我有一个TextBox用户可以在其中输入搜索词。它绑定到string Term我的属性view-model。我想在内容发生变化时进行搜索查询。但我想在一个单独的线程中延迟查询。

例如,当用户输入一个字母时,我想等待0.3 秒,如果用户在这段时间内(0.3 秒)更改输入,计时器将重置并重新启动。否则,我会启动一个新线程并执行搜索查询。在执行查询时,如果用户再次更改术语,则中止上一个查询并重新开始。

我知道如何在带有线程和Timer类的 Windows 窗体中做到这一点。但我是新手WPF,我正在搜索是否有为 WPF 线程功能指定的方法(或者可能是一种性能更好的方法)。

你有什么想法吗?你能帮助我吗?

4

3 回答 3

2

你可以使用DispatcherTimer. 在每次按键时,如果计时器已经在运行,则停止计时器,然后启动它。我相信(你应该检查一下!)那会重置它。

如果它触发,那么您将获取文本框中的当前值并开始在单独的线程中执行操作(例如,使用Task.Factory.StartNew,如果您使用的是 .NET 4,或者BackgroundWorker,或者只是创建一个新线程)。

基本上,这将“新线程”部分与“我真的想做某事”部分分开,将所有内容都保留在 UI 线程上,直到您决定确实想要做某事(并且您知道您的价值)想用)。

于 2012-05-09T20:36:38.777 回答
0

您可能想查看 Microsoft 的Reactive Extensions。一旦经过一定的延迟,Rx 提供了一种将这些类型的事件聚合为单个事件的方法。

Phil Haack(前 Microsoft)在他的博客上有一篇很好的文章,他谈到了节流功能。

于 2012-05-09T20:36:32.160 回答
0

这只是建立在 Jon Skeets 所说的基础上。把复选标记给他。.stop()似乎重置了timer.

public MainWindow()
{
    InitializeComponent();

    backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.WorkerSupportsCancellation = true;
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

    dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
    dispatcherTimer.Interval = new TimeSpan(0, 0, 4);
}

public string Input
{
    get { return input; }
    set
    {
        if (value == input) return;
        value = value.Trim();
        input = value;
        NotifyPropertyChanged("Input");

        if (backgroundWorker1.IsBusy) backgroundWorker1.CancelAsync();
        dispatcherTimer.Stop();                
        dispatcherTimer.Start();
    }
 }

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    dispatcherTimer.Stop();
    if (!backgroundWorker1.IsBusy)
    {
        backgroundWorker1.RunWorkerAsync(Input);
    }
}
于 2012-05-10T00:05:26.543 回答