2

入力機能に合わせて検索を実装しようとしています (デフォルトの電子メール アプリの検索機能のような) - 50 個のアイテムを含むリスト ボックスがあります - 各アイテムは文字列フィールドを持つクラス オブジェクトにバインドされています...文字列フィールドの1つに検索ボックスのテキストがあるアイテムを検索して表示するには-これは、ユーザーがテキストボックスにキーを入力するためです...いくつかのアプローチを試しました->

1 >> CollectionViewSource を使用する
- CollectionViewSource を DB のすべてのアイテムに
バインドする - リスト ボックスを CollectionViewSource にバインドする
- CollectionViewSource のフィルター プロパティを設定する - アイテムの検索ボックス内のテキストを検索する関数に、 e.Accepted を設定します - すべてのキーアップ イベントで
- フィルタリングは正常に動作しますが、50 個のアイテムでは遅くなります :( - 各アイテムを取得し、e.Accepted プロパティを true に設定するかどうかをチェックするフィルターの cos を推測します
.... ロード時に 1 つの DB 呼び出ししかしCollectionViewSourceでファイラーにどの要素を表示するかを決める処理が大変なようです

2 >> フィルター @ DB レベル
- キーアップ時 - 検索ボックス内のテキストを ViewModel に送信し、そこで関数が検索文字列を持つオブジェクトの ObservableCollection を返します
- ObservableCollection はリストボックスにバインドされ
ます ....あまり処理されません @ the最上位レイヤーですが、キープレスごとに複数の DB 呼び出し - それでも遅いですが、アプローチ 1 よりは少し高速です

あなたが推奨する他のアプローチはありますか?または上記のアプローチをさらに最適化するための提案はありますか? - 検索をスムーズに機能させるための微調整はありますか?

初めてのモバイル開発 :) ... よろしくお願いします :)

4

1 に答える 1

1

検索アクションを x ミリ秒遅らせることで、検索プロセスをさらに最適化して、ユーザーが検索条件の書き込みを続行できるようにすることができます。このように、新しいタイプの各文字は、アクションがトリガーされる最後の文字まで、検索アクションを xxx ミリ秒遅延させます。10 回の呼び出しではなく、1 回の呼び出しでパフォーマンスが向上します。技術的に言えば、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 に答える