Silverlight 2 中的分页可搜索列表框控件





4.00/5 (2投票s)
如何在 Silverlight 2 ListBox 上实现分页和过滤。
引言
我需要在 Silverlight 2 项目中使用 ListBox
控件来显示大量项目(大约 1500 个玩家姓名),我遇到了一些很大的性能问题:在绑定 ListBox
(只是设置其 ItemSource
属性)时,渲染加载了项目的最终控件需要的时间越来越长。从用户体验的角度来看,这是无法接受的。好吧,每个人可能会问“向用户显示如此多的元素有什么用?” 事实上,在我看来,一个旨在显示如此大的项目列表而没有任何用户过滤功能的界面,都是糟糕的设计结果。但是,我确实遇到了这种情况:向用户提供所有 1500 个玩家的字母列表,让他们可以使用过滤器搜索玩家,或者最终按字母顺序滚动列表。
我立即意识到,解决方案是向用户提供一个“模拟”的完整列表:仅加载前几个项目,让他们认为它是完整的列表,然后拦截滚动操作以实际加载更多项目。换句话说:类似于我们在 MS Access 或 SQL Server 等产品的 GUI 中看到的记录延迟加载。但是,即使在“按需”加载项目后,由于加载的项目数量增加,列表在滚动时变得越来越重,并且性能问题再次出现。然后,我决定放弃“渐进式加载”方法,转而采用“分页加载”方法,并结合搜索功能。以下段落描述了我如何实现这个简单的想法。
“可分页搜索的 ListBox 控件”如何工作
附件中的示例代码包含三个实验性的 ListBox
,用于显示大量项目,这些项目是在内存中生成的(并由 AllItems
列表托管)。
在这三个示例中,我都使用了经典的、标准的 Silverlight 2 ListBox
控件,但方式不同。在这三个示例中,搜索功能都由以下简单函数提供,该函数使用 LINQ 表达式仅从完整列表中提取包含给定字符串的项目
Private Function FilterItems(ByVal FilterTerm As String) As IEnumerable(Of String)
Dim result As IEnumerable(Of String)
If FilterTerm = "" Then
' No filter currently applied
result = AllItems
Else
' Find out (locally, in memory) the subset of Items containing the search term
result = From s In AllItems Where
s.ToString().ToLower().Contains(FilterTerm.ToLower()) Select s
End If
Return result
End Function
在第一个 ListBox
中,执行了一个简单的绑定
lstList1.ItemsSource = AllItems
正如您可以在 Silverlight 2 上亲自实验的那样,对于 1500 个或更多元素,加载性能是无法接受的。通过使用搜索功能,用户可以缩小 ListBox
中加载的项目数量,但在输入最初几个字符时,速度仍然无法接受(直到过滤后的列表足够小以快速渲染为止)。
在第二个和第三个 ListBox
中,我使用了“分页”方法。这意味着 ListBox
包含有限数量的项目,并且向用户呈现一些视觉线索以在页面之间导航。第二个和第三个示例之间的唯一区别在于呈现给用户的视觉线索,用于导航页面:在示例 2 中,可以立即清楚地看到列表已分页;在示例 3 中,该线索作为附加列表元素集成在一起,用户只有通过向下滚动 ListBox
才能发现。通过跟踪当前显示的页码和页面尺寸,在这些情况下,绑定表达式变得像
lstList.ItemsSource = FilteredItems.Skip(PageNumber * PageDimension).Take(PageDimension)
如果 PageDimension
等于,比如,五十,则 ListBox
将永远不会包含超过 50 个项目。任何渲染速度的减慢都消失了,并且用户友好性得到了相当完整的保留。
结论
这里描述的“可分页搜索方法”非常简单,但对于我来说,它绝对是解决 Silverlight 2 ListBox
控件加载和渲染速度缓慢的需求。好消息是 Silverlight 3 上的 ListBox
控件似乎没有这些性能问题,因为它现在支持 UI 虚拟化。