C# WPF DataGrid性能-过滤器性能

C# WPF DataGrid性能-过滤器性能,c#,wpf,performance,grid,C#,Wpf,Performance,Grid,我们正处于将我们的应用程序从SilverLight转换为WPF的阶段,我们已经在这里开发了WPF 我们自己的自定义数据网格位于Silverlight的本地数据网格之上。应用程序由大量视图组成,其中 近99%的视图使用这些自定义网格 这是我们面临的最大挑战之一 与SilverLight相比,WPF版本应用程序中网格的性能。特别是过滤速度非常慢 我们已经创建了两个测试应用程序来比较和分析本机控件上的Silverlight和WPF。应用程序加载相同的数据集: 1000行混合数据-文本、bool、int

我们正处于将我们的应用程序从SilverLight转换为WPF的阶段,我们已经在这里开发了WPF 我们自己的自定义数据网格位于Silverlight的本地数据网格之上。应用程序由大量视图组成,其中 近99%的视图使用这些自定义网格

这是我们面临的最大挑战之一 与SilverLight相比,WPF版本应用程序中网格的性能。特别是过滤速度非常慢

我们已经创建了两个测试应用程序来比较和分析本机控件上的Silverlight和WPF。应用程序加载相同的数据集: 1000行混合数据-文本、bool、int和enum 绑定到混合数据的25列(5个相同的列重复5次)

从分析中,我们发现Silverlight datagrid似乎有一个特定的逻辑处理NotifyCollectionChanged.Reset事件(来自筛选的集合视图)。最终结果是整个过滤和布局操作在约700ms内完成

与此相反,WPF datagrid没有此逻辑,因此NotifyCollectionChanged.Reset被ItemCollection截获,而ItemCollection又截获了一个面板,该面板通过一个名为DegenantSwalker的类生成了一个嵌套非常深的调用树,其中包含大量递归调用。接下来是一个完整的更新周期。对于相同的过滤操作,WPF总共需要约3.7秒

是否有人经历过类似的迁移,您是否也经历过同样的问题?您是否找到了使用本机WPF datagrid的解决方案

数据如下所示。SilverLight和WPF的探查器(dotTrace)快照,以及所用源代码的摘录

SilverLight结果

WPF结果:

public class Data
{
   private CollectionViewSource viewSource = new CollectionViewSource();

   public Data()
   {
     var items = new List<Item>();
     // Create 1000 items
     viewSource.Source = items;
   }

   public ICollectionView View => viewSource.View;
}

public class Item
{
   public string Description { get; set; } = "Text here"; 
   public bool Bool { get; set; } 
   public int Value { get; set; } 
   public DateTime TimeStamp { get; set; } 
   public Test EnumValue { get; set; } 
   public static IEnumerable AvailableEnumValues => 
             Enum.GetValues(typeof(Test));
}

<DataGrid ItemsSource="{Binding View}"
 EnableColumnVirtualization="True" EnableRowVirtualization="True" 
 VirtualizingPanel.IsContainerVirtualizable="False" 
 VirtualizingPanel.IsVirtualizing="True" 
 VirtualizingPanel.VirtualizationMode="Recycling"
 VirtualizingPanel.IsVirtualizingWhenGrouping="True"
 VirtualizingStackPanel.CacheLength="2,3"
 VirtualizingStackPanel.CacheLengthUnit="Page"
 VirtualizingStackPanel.ScrollUnit="Item">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Description}" Width="100"/>
        <DataGridTextColumn Binding="{Binding Value}" Width="100"/>
        <DataGridCheckBoxColumn Binding="{Binding Bool}" Width="100"/>
        <DataGridComboBoxColumn SelectedItemBinding="{Binding EnumValue}" 
            ItemsSource="{x:Static local:Item.AvailableEnumValues}" 
            Width="100"/>
        <DataGridTextColumn Binding="{Binding TimeStamp}" Width="100"/> 
     <!-- Repeat 5 columns above 5 times -->
  </DataGrid.Columns>
</DataGrid>

1:使用深度嵌套的调用树进行筛选操作

2:更新更新周期

源代码:

public class Data
{
   private CollectionViewSource viewSource = new CollectionViewSource();

   public Data()
   {
     var items = new List<Item>();
     // Create 1000 items
     viewSource.Source = items;
   }

   public ICollectionView View => viewSource.View;
}

public class Item
{
   public string Description { get; set; } = "Text here"; 
   public bool Bool { get; set; } 
   public int Value { get; set; } 
   public DateTime TimeStamp { get; set; } 
   public Test EnumValue { get; set; } 
   public static IEnumerable AvailableEnumValues => 
             Enum.GetValues(typeof(Test));
}

<DataGrid ItemsSource="{Binding View}"
 EnableColumnVirtualization="True" EnableRowVirtualization="True" 
 VirtualizingPanel.IsContainerVirtualizable="False" 
 VirtualizingPanel.IsVirtualizing="True" 
 VirtualizingPanel.VirtualizationMode="Recycling"
 VirtualizingPanel.IsVirtualizingWhenGrouping="True"
 VirtualizingStackPanel.CacheLength="2,3"
 VirtualizingStackPanel.CacheLengthUnit="Page"
 VirtualizingStackPanel.ScrollUnit="Item">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Description}" Width="100"/>
        <DataGridTextColumn Binding="{Binding Value}" Width="100"/>
        <DataGridCheckBoxColumn Binding="{Binding Bool}" Width="100"/>
        <DataGridComboBoxColumn SelectedItemBinding="{Binding EnumValue}" 
            ItemsSource="{x:Static local:Item.AvailableEnumValues}" 
            Width="100"/>
        <DataGridTextColumn Binding="{Binding TimeStamp}" Width="100"/> 
     <!-- Repeat 5 columns above 5 times -->
  </DataGrid.Columns>
</DataGrid>

公共类数据
{
private CollectionViewSource viewSource=新的CollectionViewSource();
公共数据()
{
var items=新列表();
//创建1000个项目
viewSource.Source=项目;
}
public ICollectionView=>viewSource.View;
}
公共类项目
{
公共字符串说明{get;set;}=“Text here”;
公共bool bool{get;set;}
公共int值{get;set;}
公共日期时间时间戳{get;set;}
公共测试枚举值{get;set;}
公共静态IEnumerable AvailableEnumValues=>
Enum.GetValues(typeof(Test));
}