如何在键入时提高搜索性能?

时间:2012-06-04 10:02:51

标签: database performance windows-phone-7 search windows-phone-7.1

我正在尝试在您键入功能时实现搜索功能(如默认电子邮件应用中的搜索功能) - 我有一个包含50个项目的列表框 - 每个项目都绑定到具有字符串字段的类对象。 。我希望搜索和显示在其字符串字段中的搜索框中包含文本的项目 - 这是用户键入文本框...尝试了几种方法 - >

1>>使用CollectionViewSource
- 将CollectionViewSource绑定到DB中的所有项目 - 将列表框绑定到CollectionViewSource
- 设置CollectionViewSource的过滤器属性 - 其功能在项目的搜索框中搜索文本,并在每个键盘事件上设置e.Accepted - - 过滤工作正常但速度慢50项:( - 猜测过滤每个项目的过滤器并检查是否将e.Accepted属性设置为true
....一个DB调用加载,但似乎是很多处理来决定由CollectionViewSource在文件管理器中显示哪个元素

2>>过滤@ DB级别
- 在keyup上 - 将搜索框中的文本发送到ViewModel,其中函数返回一个ObservableCollection对象,该对象具有搜索字符串
- ObservableCollection绑定到列表框
....顶层没有多少处理,但每个Keypress上有多个DB调用 - 仍然很慢,但比Approach One快一点

你会推荐其他approch吗?或进一步优化上述方法的任何建议? - 任何调整,以使搜索顺利运作?

第一次进入移动设备开发:) ... Thanx提前:)

1 个答案:

答案 0 :(得分:1)

您可以通过将搜索操作延迟x毫秒来进一步优化搜索过程,以允许用户继续编写搜索条件。这样,每个新类型的char都会将搜索操作延迟xxx毫秒,直到触发操作的最后一个char,只需一次调用就可以获得更好的性能,而不是说10次调用。从技术上讲,您可以通过使用Timer类来实现此目的。 在这里,您将找到一个示例源代码示例,向您展示如何实现它。

    private void txtSearchCriteria_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (txtSearchCriteria.Text == "Search ...")
            return;

        if (this.deferredAction == null)
        {
            this.deferredAction = DeferredAction.Create(() => ApplySearchCriteria());
        }

        // Defer applying search criteria until time has elapsed.
        this.deferredAction.Defer(TimeSpan.FromMilliseconds(250));
    }


    private DeferredAction deferredAction;


    private class DeferredAction
    {
        public static DeferredAction Create(Action action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            return new DeferredAction(action);
        }

        private Timer timer;

        private DeferredAction(Action action)
        {
            this.timer = new Timer(new TimerCallback(delegate
            {
                Deployment.Current.Dispatcher.BeginInvoke(action);
            }));
        }

        public void Defer(TimeSpan delay)
        {
            // Fire action when time elapses (with no subsequent calls).
            this.timer.Change(delay, TimeSpan.FromMilliseconds(-1));
        }
    }

    public void ApplySearchCriteria()
    {
        ICollectionView dataView = this.ViewSource.View;

        string criteria = this.txtSearchCriteria.Text;
        string lowerCriteria = criteria.ToLower();
        using (dataView.DeferRefresh())
        {
            Func<object, bool> filter = word =>
            {
                bool result = word.ToString().ToLower().StartsWith(lowerCriteria);
                return result;
            };

            dataView.Filter = l => { return filter.Invoke(l); };
        }

        this.lstWords.ItemsSource = dataView;                       
        if (this.lstWords.Items.Count != 0)
        {
            this.lblError.Visibility = Visibility.Collapsed;
        }
        else
        {
            this.lblError.Visibility = Visibility.Visible;
        }
    }