Search code examples
wpfmultithreadingautocompletebox

Wpf toolkit AutoCompleteBox search on background thread


I'm using WPF toolkit AutoCompleteBox that its itemsSource is a list of milions of objects.

Does the AutoCompleteBox use for the searching a background thread and if it doesn't how can I make it to.


Solution

  • No, it does not use a background thread. You can read the source yourself in the WPF Tookit. However, it is flexible enough to allow you to do it yourself on a background thread.

    You can use this approach:

    • Handle the Populating event: cancel it, and start your background worker using SearchText
    • When the background worker is complete: set the ItemsSource and call PopulateComplete

    There is a complete example of this in the MSDN documentation:

    That example uses a asynchronous web service to populate the auto-complete data but the same idea applies to searching a very large dataset. The background thread

    Update:

    Here is a complete example with the search occurring on a background thread. It includes a one-second sleep to simulate a long search:

    private class PopulateInfo
    {
        public AutoCompleteBox AutoCompleteBox { get; set; }
        public string SearchText { get; set; }
        public IEnumerable<string> Results { get; set; }
    }
    
    private void AutoCompleteBox_Populating(object sender, PopulatingEventArgs e)
    {
        var populateInfo = new PopulateInfo
        {
            AutoCompleteBox = sender as AutoCompleteBox,
            SearchText = (sender as AutoCompleteBox).SearchText,
        };
        e.Cancel = true;
        var ui = TaskScheduler.FromCurrentSynchronizationContext();
        var populate = Task.Factory.StartNew<PopulateInfo>(() => Populate(populateInfo));
        populate.ContinueWith(task => OnPopulateComplete(task.Result), ui);
    }
    
    private PopulateInfo Populate(PopulateInfo populateInfo)
    {
        var candidates = new string[] {
            "Abc",
            "Def",
            "Ghi",
        };
        populateInfo.Results = candidates
            .Where(candidate => candidate.StartsWith(populateInfo.SearchText, StringComparison.InvariantCultureIgnoreCase))
            .ToList();
        Thread.Sleep(1000);
        return populateInfo;
    }
    
    private void OnPopulateComplete(PopulateInfo populateInfo)
    {
        if (populateInfo.SearchText == populateInfo.AutoCompleteBox.SearchText)
        {
            populateInfo.AutoCompleteBox.ItemsSource = populateInfo.Results;
            populateInfo.AutoCompleteBox.PopulateComplete();
        }
    }