我有一个WP8应用程序,我在本地数据库中有一些项目。我有两个实体(为了这个问题的目的) - 文件夹和文件。我想在带有自定义datatemplate的列表框中显示这些内容。 我从localdb中选择项目,创建一个包含两个实体模型的模型类型的observablecollection(用于统一表示),然后将其绑定到列表框。这种方法适用于中等数字的结果(例如,最多1000个项目)。 但是,对于较大的列表(例如10K项),我会出现内存异常。
除此之外,即使是1k,性能显然也不是很棒,因为算法基本上是为每个获取的实体创建一个新模型。
有没有办法以与NSFetchedResultsController操作相同的方式将列表框直接绑定到查询结果? 更新因此,根据评论中的建议,我尝试按需加载数据。但是,由于列表框没有虚拟化,通过将它们添加到可观察集合中将大约800个项目加载到列表框中,我最终得到退出代码 - 2147220978(0x8004020e),这表明图形数据只是重载了可用资源。所以我写了一些代码,在向下滚动时删除可观察集合中的顶级项目,一切都很棒。但是,尝试检测用户何时向上滚动会破坏所有内容。向下滚动时,我使用linq到可视树,抓住ScrollViewer并检查VerticalOffset是否是> = ScrollableHeight。但是当检查用户是否滚动到顶部时,我必须检查VerticalOffset == 0.0,但是如果用户已经在顶部,我使用的DependencyPropertyListener将不会引发任何事件,即使我的项目已被添加.. e.g:
var scrollViewer = (ScrollViewer)CurrentItemTiles.Descendants<ScrollViewer>().FirstOrDefault();
var listener = new DependencyPropertyListener();
listener.Changed += delegate(object o, BindingChangedEventArgs args)
{
if (scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight)
{ // scrolling down. This works well even when the user keeps holding the scroll bar down, e.g. scrolls through all pages.
LoadItems(Page + 1);
if (CurrentItems.Count > 200)
{
for (int i = 0; i <= 50; i++)
{
CurrentItems.RemoveAt(i);
}
}
}
else if (scrollViewer.VerticalOffset == 0.0 && Page > 4)
{
// This works well when the user is down below and they scroll up.
// If they want to keep going UP, they have to scroll down a little, then up again,
// and again and again. This doesnt feel natural at all.
var count = CurrentItems.Count - 1;
// second argument signifies that we will add items to the top of ObservableCollection<TModel>
LoadItems(Page - 4, true);
for (int i = 0; i <= 50; i++)
{
if (CurrentItems.Count >= (count + i)) CurrentItems.RemoveAt(count + i);
}
}
};
var binding = new Binding("VerticalOffset") { Source = scrollViewer };
listener.Attach(scrollViewer, binding);