Windows Community Toolkit --> TokenizingTextBox dynamic change of SuggestedItemsSource

134 Views Asked by At

is it possible to change the SuggestedItemsSource in a TokenizingTextBox dynamically?

Currently my list consists of all entries, but as soon as the user starts typing, the suggestions should only match the input.

I tried it like that:

XAML

                            <controls:TokenizingTextBox Header="Model"
                                                        PlaceholderText="Type a model name"
                                                        Margin="0,24,0,0"
                                                        HorizontalAlignment="Stretch"
                                                        TextMemberPath="Text"
                                                        TokenDelimiter=","
                                                        SuggestedItemsSource="{Binding SuggestionList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                        TokenItemAdded="TokenizingTextBox_TokenItemAdded"
                                                        TextChanged="TokenizingTextBox_TextChanged"/>

Code behind

        private void TokenizingTextBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            ((ViewModels.FolderName.ViewModel)DataContext).searchName(sender.Text);
        }

ViewModel

      private List<string> _suggestionList = new List<string>();
      public List<string> SuggestionList
      {
          get => _suggestionList ;
          set => SetProperty(ref _suggestionList , value);
      }


     internal void searchName(string searchString )
     {
         SuggestionList.Clear();
         for (int i = 0; i < originalData.Count; i++)
         {
             if (originalData[i].Name.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
             {
                 SuggestionList.Add(originalData[i]);
             }

         }
     }

But when typing letters, the program crashes without usable exception. Is it not possible or what I am doing wrong?

I hope someone can help me or give me a good hint :)

What I know

  • The crash is due to: SuggestionList.Clear()

But if remove the clear part, the suggestion list is also not updated dynamic? Here my expectation would be that the SuggestionList gets bigger and bigger, because duplicate entries should be present.

My expactation is:

  • Dynamic change of SuggestedItemsSource, so that the user will only see suggestions matches with his typed letters
1

There are 1 best solutions below

8
Andrew KeepCoding On BEST ANSWER

Something like this should work:

TokenizingTextBoxEx.cs

using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace TokenizingTextBoxExample;

public class TokenizingTextBoxEx : TokenizingTextBox
{
    public TokenizingTextBoxEx()
    {
        this.Loaded += TokenizingTextBoxEx_Loaded;
    }

    private void TokenizingTextBoxEx_Loaded(object sender, RoutedEventArgs e)
    {
        if (this.FindDescendant<AutoSuggestBox>() is AutoSuggestBox autoSuggestBox)
        {
            autoSuggestBox.TextChanged -= AutoSuggestBox_TextChanged;
            autoSuggestBox.TextChanged += AutoSuggestBox_TextChanged;
        }
    }

    // This is based on the WinUI 3 Gallery AutoSuggestBox sample code.
    private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
    {
        if (args.Reason is AutoSuggestionBoxTextChangeReason.UserInput &&
            this.SuggestedItemsSource is IEnumerable<string> suggestedItems)
        {
            List<string> suitableItems = new();
            string[] splitText = sender.Text.ToLower().Split(" ");

            foreach (string item in suggestedItems)
            {
                bool found = splitText.All((key) =>
                {
                    return item.ToLower().Contains(key);
                });

                if (found)
                {
                    suitableItems.Add(item);
                }
            }

            if (suitableItems.Count == 0)
            {
                suitableItems.Add("No results found");
            }

            sender.ItemsSource = suitableItems;
        }
    }
}

NOTE:

FindDescendant comes from the CommunityToolkit.WinUI.Extensions NuGet package.