将WrapPanel虚拟化为ListView's ItemsTemplate
本文关键字:ItemsTemplate ListView WrapPanel 虚拟化 | 更新日期: 2023-09-27 18:14:02
我有一个ListView
在我的窗口。将ListView
的默认ItemsPanel
替换为WrapPanel
。我还有一个DataTemplate
,因为它是ListViewItem
s。在运行时,主窗口将不响应一段时间,因为ListView
有超过700(并不断增加)ListViewItem
s(从数据绑定)。是否有办法保持主窗口响应?
可选:当ListView
还没有准备好,我想要一个文本(或ProgressBar
如果可能的话)显示在ListView
上,说一些像"请等待…"或"加载项目…"。
<ListView x:Name="MyListView" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" HorizontalAlignment="Left" Height="577" VerticalAlignment="Top" Width="902" ScrollViewer.HorizontalScrollBarVisibility="Auto" Foreground="Black" Margin="10,10,0,0" ScrollViewer.CanContentScroll="True" BorderBrush="#FFC54B4B" BorderThickness="3" Background="White">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxWidth="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
编辑:我试过了:
List<something> MyList = new List<something>();
ThreadPool.QueueUserWorkItem(_ =>
{
( Create MyList here...)
Dispatcher.BeginInvoke(new Action(() =>
{
MyListView.ItemsSource = MyList;
}));
});
主窗口仍然没有响应,直到ListView准备好。
你使用的面板(WrapPanel)不能做UI虚拟化(不像VirtualizingStackPanel在默认的ListView ItemPanel模板中使用)。这意味着您的所有项目都被渲染,甚至是那些目前不可见的项目。据我所知,WPF没有内置的虚拟化封装面板,因此您可以尝试一些免费的虚拟化封装面板(例如- http://virtualwrappanel.codeplex.com/),但我不能说它们有多好,我使用的是Telerik的版本,它不是免费的。另一个选择是切换回VirtualizingStackPanel。除此之外,确保在非ui线程上加载项目(如另一个答案所述)。
如果UI线程正在执行长时间操作,它将无法处理UI请求。这也被称为不回应。这样使用ThreadPool
:
private void operation_Click(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(_ =>
{
var result = LongTimeOperation();//set the operation in another thread so that the UI thread is kept responding
//use the Dispatcher to "return" to the UI thread
Dispatcher.BeginInvoke(new Action(() =>
{
//Use result
}));
});
}
在谷歌上搜索了一段时间后。多亏了这篇文章,虚拟化WrapPanel并非不可能!方法如下:
- 从这里下载代码
- 添加到您的项目(在VS2010:项目>添加现有项目)
-
将名称空间添加到XAML:
xmlns:mwc="clr-namespace:MyWinCollection"
-
使用
VirtualizingWrapPanel
作为ListView
的ItemsTemplate
:<ListView x:Name="MyListView" ItemsSource="{StaticResource ItemCollection}"> <ListView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingWrapPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView>
完成了!
由于不是所有的项目都被一次呈现,主窗口现在是完全响应的。
希望这有帮助!: D
顺便说一句,谢谢你们!你们帮了我大忙。