Directly to the point. My list view looks like the following xaml (Not 100% the same but should be detailed enough)
<ListView ItemsSource="{Binding Result}"
SelectedItem="{Binding Selected}"
HasUnevenRows="True">My content...</ListView>
This is bound to my view model which looks like this
private CancellationTokenSource cts = null
private CancellationToken ct = CancellationToken.None
private List<Task> tasks = new List<Task>()
public ObservableCollection<T> Source = new ObservableCollection<T>()
public ObservableCollection<T> Result = new ObservableCollection<T>()
public string Query
It also have the following method. This method is where my problem is. The method should behave like this:
- Get all elements from source (doesn't matter from where)
- Start a task which will run in the background (to build the list step by step, to reduce the number of at the same generated listview items, performance)
- So it will add the elements to the result step by step (In my case 100 elements max at the same time)
And here is the code Note: Source has been successfully loaded and the elements are in there
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
tasks.Clear();
cts = new CancellationTokenSource();
ct = cts.Token;
Result.Clear();
// Create background task
tasks.Add(Task.Factory.StartNew(() =>
{
var validItems = Source.Where(c => ((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c => ((ISearchQueryViewModel)c).Aktive).ToList();
if (ct.IsCancellationRequested)
return;
var numberOfValidItemsToAdd = validItems.Count;
var currentIndex = 0;
while (numberOfValidItemsToAdd > 0)
{
if (ct.IsCancellationRequested)
return;
var numberOfIndexes = 100;
if (numberOfValidItemsToAdd < 100)
numberOfIndexes = numberOfValidItemsToAdd;
for (int i = 0; i < numberOfIndexes; i++)
{
currentIndex++;
if (ct.IsCancellationRequested)
return;
Result.Add(validItems[i]);
}
numberOfValidItemsToAdd -= numberOfIndexes;
for (int i = 0; i < 100; i++)
{
if (ct.IsCancellationRequested)
return;
Thread.Sleep(50);
}
}
}, ct));
This result the error
Unhandled Exception:
Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). Native stack trace: 0
CoreFoundation 0x00000001104da12b __exceptionPreprocess + 171 1 libobjc.A.dylib 0x000000011dda6f41 objc_exception_throw + 48 2 CoreFoundation
0x00000001104df2f2 +[NSException raise:format:arguments:] + 98 3
Foundation 0x0000000111109d69 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193 4
UIKit 0x0000000114652209 -[UITableView _endCellAnimationsWithContext:] + 19416 5 UIKit 0x000000011466d075 -[UITableView endUpdates] + 75 6
MobileClient.iOS 0x000000010fdfd9f9 xamarin_dyn_objc_msgSend + 217 7 ???
0x000000013f12d452 0x0 + 5353165906