正如大多数WPF开发人员所知,设置ScrollViewer.CanContentScroll为false禁用虚拟化; 但我想知道它是如何工作的,因为我尝试启用虚拟化,同时设置ScrollViewer.CanContentScroll到false.
我目前正在开发一种可视化工具,可以在Canvas上绘制路径,椭圆等WPF形状.我已经实现了一种虚拟化方法,其中Shapes被动态销毁和创建,具体取决于它们的可见性.然而,即使只有600个椭圆可见,该应用程序似乎很难.
我有什么选择加快速度?我正在考虑将分组的Shapes(一次说500个)渲染为透明位图,并且只在Canvas上绘制这些.但我不知道这是不是一个好主意......从我收集的内容来看,这需要某种黑客攻击,如果应用了转换:
VisualBrush shapeBrush = new VisualBrush(shape);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
using (drawingContext)
{
drawingContext.DrawRectangle(shapeBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
}
renderTarget.Render(drawingVisual);
Run Code Online (Sandbox Code Playgroud)
那么使用一个大的WritableBitmap呢?这会是另一种方法吗?
UI虚拟化是一个尴尬的术语,它描述了WPF UI控件,它根据需要加载和配置子元素(基于它们的可见性)以减少内存占用.ListBox和ListView默认使用名为VirtualizingStackPanel的类来实现更高的性能.
我发现这个控件非常有用,它是一个虚拟化的画布,它生成一个可滚动的Canvas对象,用四叉树管理它的子对象.它产生了一些很好的结果,可以很容易地根据您的需要进行调整.
是否有其他指南或示例wpf控件可以解决此问题?也许通用的那个处理gui对象在其他语言和工具包中的动态内存分配?
我找到了几个替代方案,这个CodePlex项目和这个商业项目,但前者在我的测试中效率极低,后者很好,成本为$$.我也发现了这个实现,但它不是一个WrapPanel作为"TilePanel",并且不支持自动调整大小的项目(尽管看起来确实很快).
我也发现了一些关于如何在这里写自己的"暗示" ,但是当开发人员在公司时间开发它时,他无法发布他的全部资料.
有没有人花时间实现一个像样的VirtualizingWrapPanel并公开发布,或者我将不得不花一天时间写自己的?
几乎没有关于设置影响的信息;
VirtualizingStackPanel.IsVirtualizing="True"
Run Code Online (Sandbox Code Playgroud)
和
EnableRowVirtualization="True" EnableColumnVirtualization="True".
Run Code Online (Sandbox Code Playgroud)
有人可以澄清一下有什么区别吗?
此外,作为额外的奖励,任何人都可以澄清EnableRowVirtualization和EnableColumnVirtualization是否在3.5网格上实际执行任何操作,因为MSDN文档仅将这些属性列为4.0,但它们肯定存在于3.5中?
谢谢.
我需要处理WPF应用程序中的大量数据.
我已将大型集合绑定到ListView,并且我使用ItemContainerStyle将列表项的IsSelected属性绑定到我的对象的IsSelected属性,以便在选中该项时ListView,my objects的IsSelected属性也将设置为true.通过这样做,我可以轻松地仅对列表中已选择的对象执行命令.
我在ListView中使用UI虚拟化,因为应用程序会缓慢.但是因为我的整个集合中只有一部分在列表中可见,所以当我使用CTRL + A选择列表中的所有项目时,只有加载的项目的IsSelected属性设置为true.不可见的项目(虚拟化的项目)的IsSelected属性设置为false.这是一个问题,因为当我选择列表中的所有项目时,我希望该IsSelected属性对于集合中的所有项目都设置为true.
我已经创建了一些示例代码来说明问题:
MainWindow.xaml
<Window x:Class="VirtualizationHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" x:Name="wnd">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Click me" Click="Button_Click" />
<ListView Grid.Row="1" ItemsSource="{Binding Path=Persons, ElementName=wnd}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml.cs
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace VirtualizationHelp
{
public partial class MainWindow : Window
{ …Run Code Online (Sandbox Code Playgroud) 如果TreeView设置如下,什么可以阻止TreeView虚拟化?
<TreeView
ItemsSource="{Binding}"
VirtualizingStackPanel.IsVirtualizing="True">
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
<TreeView.ItemContainerStyle>
<Style
TargetType="{x:Type TreeViewItem}">
<Setter
Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Run Code Online (Sandbox Code Playgroud)
我有一个不虚拟化的,当我扩展节点(并使用snoop检查)时,我已经创建了所有的TreeViewItems.我想知道是否有一些容器组合会阻止TreeView虚拟化其内容.(比如在StackPanel中托管它)
我使用StackPanel垂直布局几个控件(即标题,子标题,列表框,分隔符,列表框等).
StackPanel是ScrollViewer的子代,以确保其内容始终可滚动.
StackPanel中的一个控件是ListBox.
其ItemsSource是绑定到大型集合的数据,复杂的DataTemplate用于实现每个项目.
不幸的是,我的性能(高CPU /内存)非常糟糕.
我试过了
但是表演没有区别.我猜测StackPanel在测量期间给它的内部儿童无限高度?
当我用其他面板/布局(例如,Grid,DockPanel)替换ScrollViewer和StackPanel并且性能显着提高时,这让我相信瓶颈和解决方案都在虚拟化中.
有什么方法可以改善这个视图的CPU /内存性能吗?

[更新1]
原始示例项目:http://s000.tinyupload.com/index.php?file_id = 29810707815310047536
[更新2]
我尝试重新设置/模板化TreeView/TreeViewItems来提供以下示例.它仍然需要很长时间才能启动/使用相同的高内存.但是一旦加载,滚动感觉比原始样本响应更快.
想知道是否还有其他方法可以进一步改善启动时间/内存使用情况?
重新设计的TreeView项目:http://s000.tinyupload.com/index.php?file_id = 00117351345725628185
[更新2]
pushpraj的解决方案就像一个魅力
TreeView没有ScrollIntoView()方法,
唯一的方法是调用TreeVewItem.BringIntoView()相应的数据项容器。
但如果节点不可见并且尚未生成容器,ItemsControl.ItemContainerGenerator.ContainerFromItem()将返回null。
因此应该有某种方法强制 ItemContainerGenerator 为项目创建容器。
合理的问题是:节点如何扩展并且保持不可见?!
简单的!IsExpanded与VM的属性绑定。UI 虚拟化按预期工作:
仅当手动滚动到项目完成时,才会调用 TreeViewItem.Expanded 的事件处理程序。
我正在使用框架.NET 4.0的WPF应用程序
我有一个DataGrid的问题:每行有2个命令:
public ICommand MoveUpOrderPipeCommand
{
get
{
if (_moveUpOrderPipeCommand == null)
{
_moveUpOrderPipeCommand = new Command<OrderPipeListUIModel>(OnMoveUpOrderPipe, CanMoveUpOrderPipe);
}
return _moveUpOrderPipeCommand;
}
}
private bool CanMoveUpOrderPipe(OrderPipeListUIModel orderPipe)
{
if (OrderPipes == null || !OrderPipes.Any() || OrderPipes.First() == orderPipe)
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
MoveDown有相同的命令(可以执行检查该行是否不是最后一行)
和DataGrid:
<DataGrid Grid.Row="1" IsReadOnly="True" ItemsSource="{Binding OrderPipes}" SelectionMode="Extended">
<DataGrid.Columns>
<DataGridTextColumn Header="Diam. (mm)" Binding="{Binding Diameter}" Width="120"> </DataGridTextColumn>
<DataGridTextColumn Header="Lg. (m)" Binding="{Binding Length}" Width="120"></DataGridTextColumn>
<DataGridTextColumn Header="Ep. (mm)" Binding="{Binding Thickness}" Width="120"></DataGridTextColumn>
<DataGridTextColumn Header="Ondulation" Binding="{Binding Ripple}" Width="120"></DataGridTextColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate> …Run Code Online (Sandbox Code Playgroud) wpf ×10
.net ×2
performance ×2
treeview ×2
c# ×1
datagrid ×1
icommand ×1
listbox ×1
mvvm ×1
scrollviewer ×1
wpfdatagrid ×1
wrappanel ×1