C# 表单(IOS)动态构建列表视图项(ObservableCollection和Task.Factory)
直截了当。 我的列表视图看起来像下面的xaml(不是100%相同,但应该足够详细)C# 表单(IOS)动态构建列表视图项(ObservableCollection和Task.Factory),c#,ios,objective-c,listview,xamarin.forms,C#,Ios,Objective C,Listview,Xamarin.forms,直截了当。 我的列表视图看起来像下面的xaml(不是100%相同,但应该足够详细) 我的内容。。。 这将绑定到我的视图模型,如下所示 private CancellationTokenSource cts = null private CancellationToken ct = CancellationToken.None private List<Task> tasks = new List<Task>() public ObservableCollection&l
我的内容。。。
这将绑定到我的视图模型,如下所示
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
private CancellationTokenSource cts=null
私有CancellationToken ct=CancellationToken.None
私有列表任务=新列表()
公共ObservableCollection源=新ObservableCollection()
公共ObservableCollection结果=新ObservableCollection()
公共字符串查询
它也有以下方法。这就是我的问题所在。该方法的行为应如下所示:
cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
tasks.Clear();
cts = new CancellationTokenSource();
ct = cts.Token;
// Result.Clear();
// Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
// Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
// Result = new ObservableCollection<T>();
while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
Result.RemoveAt(0);
// 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;
for (int i = 0; i < validItems.Count; i++)
{
if (ct.IsCancellationRequested)
return;
Result.Add(validItems[i]);
Thread.Sleep(25);
}
}, ct));
- 从源代码获取所有元素(无论从何处获取)
- 启动一个将在后台运行的任务(逐步构建列表,以减少在同一时间生成的listview项的数量,提高性能)
- 因此,它会一步一步地将元素添加到结果中(在我的例子中,同时最多100个元素)
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));
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
任务。清除();
cts=新的CancellationTokenSource();
ct=cts.Token;
Result.Clear();
//创建后台任务
tasks.Add(Task.Factory.StartNew(()=>
{
var validItems=Source.Where(c=>((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c=>((ISearchQueryViewModel)c).akctive.ToList();
如果(ct.IsCancellationRequested)
返回;
var numberOfValidItemsToAdd=有效数据项计数;
var currentIndex=0;
while(numberOfValidItemsToAdd>0)
{
如果(ct.IsCancellationRequested)
返回;
var numberOfIndexes=100;
如果(NumberOfValidItemsToAdd100)
numberOfIndexes=numberOfValidItemsToAdd;
对于(int i=0;i
这导致了错误
未处理的异常:
Foundation.MonoTouchException:引发Objective-C异常。姓名:
NSInternalInconsistencyException原因:无效更新:无效
节0中的行数。表中包含的行数
更新(1)后的现有节数必须等于
更新(1)之前该节中包含的行,加号或减号
从该节插入或删除的行数(插入1,
0)并加上或减去移入或移出的行数
该部分(0移入,0移出)。本机堆栈跟踪:0CoreFoundation 0x00000001104da12b __异常预处理+171 1 libobjc.A.dylib 0x000000011dda6f41 objc_异常_抛出+48 2 CoreFoundation
0x00000001104df2f2+[NSException raise:格式:参数:][98 3
基金会0x000 000 011109D59 -[NSAssertionHandler handleFailureInMethod:对象:文件:行号:说明::+1934
UIKit 0x0000000114652209-[UITableView _endCellAnimationsWithContext:+19416 5 UIKit 0x000000011466d075-[UITableView EndUpdate]+75 6
MobileClient.iOS 0x000000010FD9F9 xamarin_dyn_objc_msgSend+2177???
0x000000013f12d452 0x0+5353165906 注意:这个答案已经过时了,如果我找到了一个答案,我会让你继续 解决这个问题的好方法 非常感谢@depchie 正是这只虫子。我是这样决定的:
cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
tasks.Clear();
cts = new CancellationTokenSource();
ct = cts.Token;
// Result.Clear();
// Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
// Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
// Result = new ObservableCollection<T>();
while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
Result.RemoveAt(0);
// 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;
for (int i = 0; i < validItems.Count; i++)
{
if (ct.IsCancellationRequested)
return;
Result.Add(validItems[i]);
Thread.Sleep(25);
}
}, ct));
链接:
上面的代码(在接下来的几次更新之后,问题中的代码应该是这样的^^^^^)
再次感谢您,祝您度过愉快的一天c:
编辑:
我还可以摆脱这种有线外观的方法,因此我的代码现在看起来完全像这样:
cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
tasks.Clear();
cts = new CancellationTokenSource();
ct = cts.Token;
// Result.Clear();
// Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
// Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
// Result = new ObservableCollection<T>();
while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
Result.RemoveAt(0);
// 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;
for (int i = 0; i < validItems.Count; i++)
{
if (ct.IsCancellationRequested)
return;
Result.Add(validItems[i]);
Thread.Sleep(25);
}
}, ct));
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
任务。清除();
cts=新的CancellationTokenSource();
ct=cts.Token;
//Result.Clear();
//解决方法请参见:https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
//错误:https://bugzilla.xamarin.com/show_bug.cgi?id=59896
//结果=新的ObservableCollection();
而(Result.Count>0)//10000个元素,可能会导致相同的错误
结果:RemoveAt(0);
//创建后台任务
tasks.Add(Task.Factory.StartNew(()=>
{
var validItems=Source.Where(c=>((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c=>((ISearchQueryViewModel)c).akctive.ToList();
如果(ct.IsCancellationRequested)
返回;
for(int i=0;iMyObservableCollection.Insert(MyObservableCollection.Count, myNewObject);
Result = new ObservableCollection<T>(GetNewList());