3

I have a custom implemented control which is very memory intensive (it basically displays a group header and an accordionControl for each group). The CustomControls AccordionControlGrouping and AccordionControl both inherit from StackLayout, so I have implemented my own bindable ItemsSource. I actively change the views of the controls when the ItemsSource changes. I have optimized this change now (using LINQ and BinarySearch and that stuff) to get from 5sec. per search to 0.8sec.

This wouldn't be a problem per se, but each time a user enters a key the keyboard freezes and is therefore very unconvinient to search.

My SearchBar is bound to the command of a ViewModel like this

<SearchBar x:Name="EventSearchBar"
             Text="{Binding SearchText}"
             SearchCommand="{Binding SearchCommand}"
             Placeholder="Suche"/>

SearchCommand

private Xamarin.Forms.Command _searchCommand;
public System.Windows.Input.ICommand SearchCommand
{
    get
    {
        _searchCommand = _searchCommand ?? new Xamarin.Forms.Command(UpdateAccordionControlGrouping, CanExecuteSearchCommand);
        return _searchCommand;
    }
}
private bool CanExecuteSearchCommand()
{
    return true;
}

SearchText Property

private string _searchText = string.Empty;
public string SearchText
{
    get { return _searchText; }
    set
    {
        if (_searchText != value)
        {
            _searchText = value ?? string.Empty;
            RaisePropertyChanged(nameof(SearchText));

            // Perform the search
            if (SearchCommand.CanExecute(null))
                SearchCommand.Execute(null);
        }
    }
}

UpdateAccordionControlGrouping

private void UpdateAccordionControlGrouping()
{
  // Do some LINQ stuff to group and filter a global collection of data.
  // And raise the #OnPropertyChanged event for the ItemsSource of my 
  // custom control.
}

Now how do I make this whole process async?

I have already looked into this article and it didn't work for me.

Shanakor
  • 407
  • 1
  • 5
  • 12
  • How is this related to async-await? – Paulo Morgado Dec 28 '15 at 22:05
  • Are you actively updating the list every time the text is changed? – Paul Dec 29 '15 at 00:45
  • Sorry, for the late response. I think this is highly related to async-await because in order to make a solution where two threads work independently from each other you need async, don't you? Yes, I actively update the List (i.e. ItemsSource) every time the text has changed. I unfortunately forgot to mention, that the customControl "AccordionControlGrouping" as well as the CustomControl "AccordionControl" are both inherited from StackLayouts. (see the edit of the post for further info) – Shanakor Jan 02 '16 at 20:32

1 Answers1

0

To run your method 'UpdateAccordionControlGrouping()' async you can do this:

private async Task UpdateAccordionControlGrouping()
{
    var newgrouping = await Task.Run(() => 
        {
            //do CPU bound work here
            return newgrouping;
        });
   // assign newgrouping to the correct control
}

Be aware that if you need to change any data from the view (Bindings etc) you might get a CrossThreadException. You need to use a Dispatcher then as seen here: Dispatcher.Dispatch on the UI thread

If you work with MvvmLight you get to use the DispatchHelper Simple example of DispatcherHelper

Community
  • 1
  • 1
Florian Moser
  • 2,583
  • 1
  • 30
  • 40
  • First of all thank you for this reply! I have tried this approach now and came to see that now the Populating is going on async. However logically when a population is executing and the user presses another key, the key hangs because the gui waits for the background pupoulation to finish. I will resolve this as follows. Every time the user presses a key and the pupulating is still in process, the populating is cancelled and a new populating thread is started. – Shanakor Jan 07 '16 at 11:46
  • @Shanakor Apart from using `async` and `await` I think you should use a `loader` to escape the `freezing` issue and also `debouncing` in your approach, it would limit the number of times your handler function will repopulate the data source, its performance would increase. You can see how to implement `debouncing` in Xamarin in this nice article [link](https://www.calvinallen.net/xamarin-forms-debouncing-an-entry-field/). – Shekher Khare Jun 01 '20 at 19:20