延迟加载不可见元素
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了延迟加载不可见元素相关的知识,希望对你有一定的参考价值。
我有一个案例,我有一个gridview
/ listbox
/任何类型的项目控制和绑定到控件的项目数量是巨大的(容易约5000+标记)。
这些项中的每一项都需要具有从各种Web服务加载的各种属性。显然,联系Web服务以同时处理这些元素是不可能的。
我的问题是,是否有可能推迟加载,直到这些项目实际显示给用户?在用户中,用户向下滚动,尽管项目一直存在于集合中,但只有在实际物理渲染时才会处理它们。
我以前看过它,但我记不清楚到底在哪里。这是一种情况,其中大量股票报价在一个绑定到gridview的集合中,但是它们的属性(价格等等)在第一次显示之前是空的(通过滚动到它们各自的位置)。
希望这有点(有些)意义。
关于如何实现这一目标的任何想法?
我会尝试延迟加载和异步加载的组合: 使用虚拟列表控件。为您的项创建一个ViewModel,并使用ViewModel的实例填充您的列表(每行一个)。
在ViewModel中,创建具有默认值的属性,该默认值显示用户未加载数据。第一次访问其中一个属性时,触发加载数据异步并在收到实际数据时触发INotifyPropertyChanged
。
这将为用户提供良好的体验,大部分棘手的工作将通过虚拟化列表完成(在WPF中,这是ListBox
,ListView
,DataGrid
......)。希望这有帮助。
class LineItemVM : INotifyPropertyChanged{
bool m_loadingTriggered;
string m_name="Loading...";
string m_anotherProperty="Loading...";
public string Name{
get{
TriggerLoadIfNecessary(); // Checks if data must be loaded
return m_name;
}
}
public string AnotherProperty{
get{
TriggerLoadIfNecessary(); // Checks if data must be loaded
return m_anotherProperty;
}
}
void TriggerLoadIfNecessary(){
if(!m_loadingTriggered){
m_loadingTriggered=true;
// This block will called before your item will be displayed
// Due to the m_loadingTriggered-member it is called only once.
// Start here the asynchronous loading of the data
// In virtualizing lists, this block is only called if the item
// will be visible to the user (he scrolls to this item)
LoadAsync();
}
}
...
附加逻辑作为一个想法,您还可以创建一个外部异步加载线程,在后台加载所有数据,但有一个列表,列出应该加载更高优先级的项目。该概念与上面的示例相同,但是TriggerLoadIfNecessary
方法不是从ViewModel项加载数据,而是仅在高优先级列表中添加项,以便首先加载可能可见的元素。哪个版本更适合的问题取决于列表的用法。如果用户可能使用完整列表并且没有快速导航,则此扩展版本更好。否则原始版本可能更好。
这是一个事件,当用户滚动到最后一个数据屏幕时将通知:
using System.Windows;
using System.Windows.Controls;
public static class ScrollViewer
{
public static readonly RoutedEvent LastPageEvent = EventManager.RegisterRoutedEvent(
"LastPage",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(ScrollViewer));
private static readonly RoutedEventArgs EventArgs = new RoutedEventArgs(LastPageEvent);
static ScrollViewer()
{
EventManager.RegisterClassHandler(
typeof(System.Windows.Controls.ScrollViewer),
System.Windows.Controls.ScrollViewer.ScrollChangedEvent,
new ScrollChangedEventHandler(OnScrollChanged));
}
public static void AddLastPageHandler(UIElement e, RoutedEventHandler handler)
{
e.AddHandler(LastPageEvent, handler);
}
public static void RemoveLastPageHandler(UIElement e, RoutedEventHandler handler)
{
e.RemoveHandler(LastPageEvent, handler);
}
private static void OnScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e.ViewportHeight == 0 || e.VerticalOffset == 0)
{
return;
}
var verticalSpaceLeft = e.ExtentHeight - e.VerticalOffset;
if (verticalSpaceLeft < 2 * e.ViewportHeight)
{
var scrollViewer = (System.Windows.Controls.ScrollViewer)sender;
scrollViewer.RaiseEvent(EventArgs);
}
}
}
以上是关于延迟加载不可见元素的主要内容,如果未能解决你的问题,请参考以下文章