wpf 将 WrapPanel 虚拟化为 ListView 的 ItemsTemplate
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32720694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Virtualizing WrapPanel as ListView's ItemsTemplate
提问by Wahyu
I have a ListViewin my window. The ListView's default ItemsPanelwas replaced with WrapPanel. I also have a DataTemplatefor it's ListViewItems. In Runtime, main window will not responding for some time because the ListViewhave more than 700 (and keep increasing) ListViewItems (from data binding). Is there a way to keep the main window responsive?
ListView我的窗户里有一个。该ListView的默认ItemsPanel被替换WrapPanel。我也有一个DataTemplate为它的ListViewItems。在运行时,主窗口在一段时间内不会响应,因为ListView有超过 700 个(并不断增加)ListViewItem(来自数据绑定)。有没有办法让主窗口保持响应?
OPTIONAL: When the ListViewis not ready, i want a text (or ProgressBarif possible) show up over the ListViewand saying something like "Please Wait..." or maybe "Loading Items...".
可选:当ListView未准备好时,我希望文本(或ProgressBar如果可能)出现在上面ListView并说“请稍候...”或“正在加载项目...”。
XAML:
XAML:
<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>
EDIT:
编辑:
I tried this:
我试过这个:
List<something> MyList = new List<something>();
ThreadPool.QueueUserWorkItem(_ =>
{
( Create MyList here...)
Dispatcher.BeginInvoke(new Action(() =>
{
MyListView.ItemsSource = MyList;
}));
});
Main window is still not responding until the ListView ready.
在 ListView 准备好之前,主窗口仍然没有响应。
采纳答案by Wahyu
After googling for some time. Thx to thisarticle, Virtualizing WrapPanel is not impossible! Here's how:
谷歌搜索一段时间后。THX到这个文章,虚拟WrapPanel也不是不可能!就是这样:
- Download the code from here
- Add it to your project (In VS2010: Project > Add Existing Item)
Add the namespace to your XAML:
xmlns:mwc="clr-namespace:MyWinCollection"Use
VirtualizingWrapPanelas yourListView'sItemsTemplate:<ListView x:Name="MyListView" ItemsSource="{StaticResource ItemCollection}"> <ListView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingWrapPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView>
- 从这里下载代码
- 将其添加到您的项目中(在 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>
Done!
完毕!
Since not all items are rendered at once, the main window is fully responsive now.
由于并非所有项目都一次呈现,因此主窗口现在可以完全响应。
Hopes this help! :D
希望这有帮助!:D
Btw, thx guys! You guys saved my day.
顺便说一句,谢谢伙计们!你们拯救了我的一天。
回答by Evk
You use panel (WrapPanel) which cannot do UI virtualization (unlike VirtualizingStackPanel which is used in default ListView ItemPanel template). What that means is all your items are rendered, even those which are not visible at the moment. WPF does not have virtualizing wrap panel built-in, as far as I know, so you can try some free virtualizing wrap panels (example - http://virtualwrappanel.codeplex.com/), but I cannot say how good they are, I use version from Telerik which is not free. Another option is switch back to VirtualizingStackPanel. In addition to that, ensure that you load your items on non-UI thread (as mentioned in another answer).
您使用不能进行 UI 虚拟化的面板 (WrapPanel)(与默认 ListView ItemPanel 模板中使用的 VirtualizingStackPanel 不同)。这意味着您的所有项目都已呈现,即使是那些目前不可见的项目。据我所知,WPF 没有内置虚拟化包装面板,因此您可以尝试一些免费的虚拟化包装面板(例如 - http://virtualwrappanel.codeplex.com/),但我不能说它们有多好,我使用的不是免费的 Telerik 版本。另一种选择是切换回 VirtualizingStackPanel。除此之外,请确保您在非 UI 线程上加载您的项目(如另一个答案中所述)。
回答by Salah Akbari
If the UI thread is doing a Long-time operation it won't be able to process UI requests. This is also known as Not Responding. Use ThreadPoollike this:
如果 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
}));
});
}

