spiegelp / MaterialDesignExtensions

Material Design Extensions is based on Material Design in XAML Toolkit to provide additional controls and features for WPF apps
https://spiegelp.github.io/MaterialDesignExtensions/
MIT License
753 stars 122 forks source link

Autocomplete control suggestion popup refresh #18

Open Coloris opened 6 years ago

Coloris commented 6 years ago

Let's say I use the following IAutocompleteSource implementation :

    public class TestClass : IAutocompleteSource
    {
        public ObservableCollection<Image> ItemsLst { get; set; }
        public IEnumerable Search(string searchTerm)
        {
            searchTerm = searchTerm ?? string.Empty;
            searchTerm = searchTerm.ToLower();

            return ItemsLst.Where(item => item.imgName.ToLower().Contains(searchTerm));
        }
    }

If later on, ItemLst content changes, it will not get reflected directly in the Autocomplete suggestion popup until something new is typed (which triggers the Search() method, I imagine, and refresh the IEnumerable).

spiegelp commented 5 years ago

@Coloris This commit introduces the IAutocompleteSourceChangingItems interface and AutocompleteSourceChangingItems as an abstract implementation.

Derive your autocomplete source from AutocompleteSourceChangingItems and call the OnAutocompleteSourceItemsChanged() method, if the list changes. Then the Autocomplete will trigger a new search with the recent search term to get a new list of items.

I am planning to put it in a release next week.

Coloris commented 5 years ago

@spiegelp Been trying to implement this but triggering OnAutocompleteSourceItemsChanged() does nothing on my side (until I type something again), do you have any sample code to share ?

public class ImagesAutocomplete : AutocompleteSourceChangingItems<MyType>
{
    private ObservableCollection<MyType> _itemsLst { get; set; }

    public ImagesAutocomplete(ObservableCollection<MyType> ItemsLst)
    {
        _itemsLst = ItemsLstSrc;
        OnAutocompleteSourceItemsChanged(); //Refresh
    }

    public override IEnumerable<MyType> Search(string searchTerm)
    {
        searchTerm = searchTerm ?? string.Empty;
        searchTerm = searchTerm.ToLower();

        return _itemsLst.Where(item => item.imgName.ToLower().Contains(searchTerm));
    }
}
spiegelp commented 5 years ago

@Coloris Sorry for the late answer.

It is important that your implementation of IAutocompleteSourceChangingItems raises the AutocompleteSourceItemsChanged event after every change. The Autocomplete handles the event and starts a new search. This time the source searches on the new list.

In your code example, you call OnAutocompleteSourceItemsChanged() in the constructor. It will not be called again on the instance. Do you change your ItemsLst from some code outside? If so, you will need to handle the CollectionChanged event of the ObservableCollection. Add this line to your constructor instead:

_itemsLst.CollectionChanged += (sender, args) => OnAutocompleteSourceItemsChanged();
Coloris commented 5 years ago

@spiegelp , I tried that but despite the fact that the event fired correctly, the list is still not refreshed until I type something or clear the box.

spiegelp commented 5 years ago

@Coloris Are you expecting that the list will update although the control is not focused?

The event handler method checks for m_searchTextBox != null && m_searchTextBox.IsKeyboardFocused before triggering a search. This should prevent unnecessary searches if the control is not focused. I did that because searches might be very CPU or I/O heavy. Maybe I will add a boolean property to toggle this behavior.

Coloris commented 5 years ago

@spiegelp Even when I get the focus on it the list is still not updated, I have to type something inside of it to see a change.

Coloris commented 4 years ago

@spiegelp I've been trying to fix this issue again a few days ago and it's still present for me. I've made a little app to demonstrate the problem.

Here a little GIF to illustrates the issue : https://gfycat.com/unsightlyfamousdore Here you can download a copy of the demo app : https://drive.google.com/open?id=1zIsDVz8TS9yN6kzPPjmc8IA6JKahWI-y

If I select an item from the list and then use the clear button, it works as expected. If I search for something, then switch the source, the popup still displays the old content and it's still possible to select something from the previous list. The only way to get a refreshed content in the popup list is to type something. Also, the OnAutocompleteSourceItemsChanged() is never raised.

infirazor commented 4 years ago

@Coloris Hello buddy, did you find any solution for this? I am having same issue where i am changing the suggestion source based on selection and the suggestions are not refreshing.

I tried above method mentioned by @spiegelp but it is still not working.

@spiegelp @Coloris Please assist me on this as its very helpful control with this tiny bug.

infirazor commented 4 years ago

@Coloris

Anyways I just tricked it by changing the selected text to some random value and again making it blank by design it did refreshed the suggestions. I am using Background worker to bring the suggestions to did it in RunWorkerCompleted.

giganoide commented 2 years ago

Same situation also for me. I tried the AutocompleteSourceItemsChanged but it doesn't work. The @infirazor 's trick works but it is a little "dirty"...