Hello,
In my solution I have SfListView with up to 100 SfAutoComplete, each has same ObservableCollection (about 50k items) as DataSource.
At the beginning I had some performance problem with creating this kind of list (it takes few seconds, so not acceptable for UI), but with some trick it was possible to solve it and now it works perfect and fast. First I noticed that there is very big performance cost for sfAutoComplete.DataSource = big50kObservableCollection, but it is very slow only if sfAutoCompete.IsVisible and also it needs to be invoked from the UI thread but only if "(autoComplete.IsDropDownOpen || (autoComplete.Text.Length>0 && autoComplete.IsFocused))". Anyway, to make long story short, I could find the way to populate all with data in background thread without blocking UI.
The problem is that now I need to modify big50kObservableCollection.
1. if user select any item, I want to mark it as favorite and move (remove and insert) at the beginning of the list so next time it will be suggested from the first character.
2. if user just enter text which is not in the big50kObservableCollection I want to make it favorite and insert it at the beginning of the list.
The problem is that even if all dropdowns are closed big50kObservableCollection.Remove and big50kObservableCollection.Insert needs to be invoked from the UI thread and because of something happened during SfAutoComplete.Handle_CollectionChanged it takes very long. When 4 sfAutoComplete are connected to big50kObservableCollection simple big50kObservableCollection.Insert(0, item) or big50kObservableCollection.Remove(item) takes over 2s, so completely not acceptable.
I tried to disconnect big50kObservableCollection from all sfAutoComplete, modify it, and connect again in background thread in same way as I did at the beginning, it seems to be impossible, because it is impossible to change already connected sfAutoComplete.DataSource. sfAutoComplete.DataSource=null or sfAutoComplete.DataSource=new ObservableCollection<ItemType>() seems to be ignored.
Could you advise me any good way how to change sfAutoComplete.DataSource without blocking UI for few seconds?
Best regards and thank you in advance for your help.
Radek
private async void AutoComplete_SelectionChanged(object sender, Syncfusion.SfAutoComplete.XForms.SelectionChangedEventArgs e)
{
var bc = (BookInfoRepository)BindingContext;
string item = e.Value?.ToString();
if (!string.IsNullOrEmpty(item))
{
await ChangeDataSource(bc, item);
}
}
private async Task<string> ChangeDataSource(BookInfoRepository bc, string item)
{
return await Task.Run(() =>
{
int index = bc.Big50ObservableCollection.IndexOf(item);
bc.Big50ObservableCollection.Move(index, 0);
return string.Empty;
});
} |
private async void AutoComplete_SelectionChanged(object sender, Syncfusion.SfAutoComplete.XForms.SelectionChangedEventArgs e)
{
if (cancellationTokenSource != null)
{
cancellationTokenSource.Cancel();
}
cancellationTokenSource = new CancellationTokenSource();
try
{
var bc = (BookInfoRepository)BindingContext;
string item = e.Value?.ToString();
if (!string.IsNullOrEmpty(item))
{
await ChangeDataSource(bc, item, cancellationTokenSource.Token);
}
}
// *** If cancellation is requested, an OperationCanceledException results.
catch (OperationCanceledException ex)
{
}
catch (Exception exc)
{
}
}
CancellationTokenSource cancellationTokenSource;
private async Task<string> ChangeDataSource(BookInfoRepository bc, string item, CancellationToken cancellationToken)
{
return await Task.Run(async() =>
{
int index = bc.Big50ObservableCollection.IndexOf(item);
await Task.Delay(5000);
bc.Big50ObservableCollection.Move(index, 0);
return string.Empty;
}, cancellationToken);
} |
Hello,
Thank you for your answer and time you spend analyzing the problem. Unfortunately, I can’t agree with result. I believe it was some kind of misunderstanding so please analyze this problem little more. Maybe there will be solution.
1stPlease take a note that my collection is not 5000000 (5000k), but 50000 (50k), so 100 times smaller.
2ndThe problem is about SfAutoComplete, not SfComboBox.
I agree that putting 5000k itmes into SfCombobox may be not the best design decision but putting 50k items into SfAutoComplete seems to be supported. There is even an example in Android Syncfusion Compontnts sample app, showing very nice performance for 100k items.
Also please take a note that all problems are because some time-consuming operation have to be done in the UI thread even if there is no obvious reason for that (all dropdowns are closed). To make things worse if more than one SfAutoComplete use same source, collection modification takes 2,3,4 times more than for 1 SfAutoComplete. It seems this very time-consuming operation in UI thread is repeated many times, even if it was enough to do it once and use same result for all SfAutoComplete.
I hope you can continue investigation and find better solution (both for iOS and Android). Even if there seems to be some work around in Android (in your example) it works not so stable, throw exceptions and after more repeats usually crashes app anyway.
Best regards,
Radek