2

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

1 >> 使用 CollectionViewSource
- 将 CollectionViewSource 绑定到数据库中的所有项目
- 将列表框绑定到 CollectionViewSource
- 设置 CollectionViewSource 的过滤器属性 - 其函数在项目的搜索框中搜索文本和设置 e.Accepted - 在每个 keyup 事件上
- 过滤工作正常,但 50 个项目的速度很慢 :( - 猜测过滤器的 cos 获取每个项目并检查是否将 e.Accepted 属性设置为 true
.... 加载时调用一个 DB但似乎需要大量处理来决定 CollectionViewSource 在文件管理器中显示哪个元素

2 >> Filter @ DB level
- on keyup - 将搜索框中的文本发送到 ViewModel,其中函数返回具有搜索字符串的对象的 ObservableCollection
- ObservableCollection 绑定到列表框
.... 没有太多处理@顶层,但每个按键上都有多个数据库调用 - 仍然很慢,但比方法一快一点

您还有其他推荐的方法吗?或者有什么建议可以进一步优化上述方法?- 有什么调整可以让搜索顺利运行吗?

第一次进入移动开发:) ...提前感谢:)

4

1 回答 1

1

您可以通过将搜索操作延迟 x 毫秒来进一步优化搜索过程,以允许用户继续编写搜索条件。这样,每个新键入的字符都会将搜索操作延迟 xxx 毫秒,直到触发该操作的最后一个字符,您只需使用一次调用而不是说 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;
        }
    }
于 2012-06-06T00:07:24.087 回答