2012-03-30 101 views
23

我们目前有一个DataGrid绑定到DataTable。它还有一个模板列,其中包含CheckBox,我们以编程方式添加。本专栏的这一目的是追踪DataGrid中的多个选项。DataGrid行虚拟化显示问题

工厂用于创建CheckBox ES的每一行。

有很多记录,所以行虚拟化设置为true,以便性能可以接受。但是,我们发现一个奇怪的问题,如果我们在前10行检查一些CheckBox es,然后向下滚动约50行(网格在任何时候都有大约10行可见),还有一堆其他的CheckBox es这似乎是随机检查。

如果我们禁用行虚拟化,则此问题不存在(但性能很糟糕)。有没有办法解决?任何人都知道我们可能做错了什么?

+0

当你说删除虚拟化后的性能很糟糕,加载或滚动时可怕。如果它的负载,有一个解决方案,这将使它不可怕,滚动是另一个问题... – 2012-03-30 19:50:04

+0

它只在负载。所有性能命中都在包含DataGrid的窗口的Show方法上。通过行虚拟化,可以在DataGrid中显示2,500条记录,并显示200ms。没有行虚拟化需要28秒。 – WPFNewbie 2012-03-30 20:17:39

+0

为你增加了一些代码......前几天在工作中只需调整性能,就像魅力一样工作 – 2012-03-30 20:36:04

回答

23

如果您正在寻找速度ListView Gridview要快得多(并且功能更少)。

尝试禁用容器回收。

   <tk:DataGrid x:Name="dataGrid" 
      ItemsSource="{Binding Path=Bookings}" 
      AutoGenerateColumns="False" 
      EnableRowVirtualization="True" 
      EnableColumnVirtualization="True" 
      VirtualizingStackPanel.VirtualizationMode="Standard" 
      VirtualizingStackPanel.IsVirtualizing="True"> 
+3

如果你在VirtualisationMode之前编写IsVirtualising,你会得到异常(至少在.NET 4.5中)......你需要更改订单 – 2014-02-06 20:36:13

+0

我有一个类似的问题,除了滚动的顺序不断变化。我没有明确做虚拟化。尽管如此,这个答案有所帮助。 – 2016-09-07 08:11:24

+0

VirtualizationMode =“标准”为赢! – 2017-04-06 14:03:09

4

如果您开启虚拟化,因为数据网格的加载时间是可怕的,那么,这里的解决方案:

  • 关闭虚拟化
  • 假设/调用为“你的DataGrid的项目源绑定行“

    public IEnumerable<Row> Rows {get; set;} 
    
  • 将属性添加到您的”行“类IsVisible并切换当你要加载的数据(而不是当UI线程决定,以解决绑定和装载每个控制)

这部作品的原因,是因为当你加载网格,它会检查结合,所有的行是不可见的,所以UI线程不必旋转所有行*列来创建它们,它可以转到它需要做的下一件事情。另一方面,您可以检测什么时候方便的时间将这些行变为可见,何时View.Visibility可见,何时ViewModel从某处加载数据,等等。因此,您完全可以控制。下面我使用任务(在后台线程中)迭代我的项目源(行),但在UI线程上设置可见性。

private _isVisible = false; 

    /// <summary> 
    /// is false by default, for performance when loading first time. 
    /// </summary> 
    public bool IsVisible 
    { 
     get { return _isVisible; } 
     set 
     { 
      if (_isVisible == value) 
       return; 
      _isVisible = value; 
      RaisePropertyChanged(() => IsVisible); 
     } 
    } 
  • 在视图中,当数据网格是装载不允许它通过将行的重复,在后台线程霸占UI线程,则可见性设置为true。即使您在后台线程中,IsVisible属性更改也会触发您更新。

    private void OnGridLoaded(object sender, RoutedEventArgs e) 
    { 
        //sample bool checks, you might not need them... 
        if (firstTimeLoad && !_isDataGridLoaded) 
        { 
         Task.Factory 
          .StartNew(() => 
          { 
           /*first time loading performance tweak*/ 
           foreach (var row in _viewModel.Rows) 
            ExeOnUi(() => { row.IsVisible = true; }); 
    
           _firstTimeLoad = false; 
          }) 
        } 
    
  • 忘了补充ExeOnUi代码(你可以用其他的像whateverControl.Dispatcher.CheckAccess检查访问,我只是用Microsoft.Practices。服务定位器):

    static void ExeOnUi (Action action) 
    { 
        var srv= ServiceLocator.Current.GetInstance<IDispatchService>(); 
        if (srv.CheckAccess()) 
         action.Invoke(); 
        else 
         srv.Invoke (action); 
    } 
    
1

我正好碰上类似的问题,它的加入UpdateSourceTrigger=PropertyChanged到绑定后解决。

<DataGridTemplateColumn Header="Visible"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <CheckBox IsChecked="{Binding IsShown,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn>