WPF DataGrid列虚拟化

WPF DataGrid列虚拟化

问题描述:

我试图在我的DataGrid上执行水平虚拟化。 我收藏的类型是:WPF DataGrid列虚拟化

List<string[]> 

它是第一个维度的长度为64,第二个是大约5000

我一直在使用Paul McClean's VirtualCollection实现垂直虚拟化

我IItemsProvider封装一个迭代其返回项目的字符串[],代表 在我的表中的一行。

我ItemsProvider:

public class ArrayItemProvider<I,T> :IArrayItemProvider, IItemsProvider<T[]> where I : IList<T> 
{  
    public int FetchCount() 
    { 
     return 64; 
    } 

    public IList<T[]> FetchRange(int startIndex, int count) 
    { 
     return _iterator.Skip(startIndex).Take(count).ToList(); 
    } 
} 

迭代器:

public class ArrayItemIterator<I, T> : IArrayItemIterator<T> where I : IList<T> 
{    
    public IEnumerator<T[]> GetEnumerator() 
    { 
     for (int i = 0; i < _arrayItemLength; i++) 
     { 
      T[] arr = new T[_extent]; 

      for (int j = 0; j < _extent; j++) 
      { 
       arr[j] = _items[j][i]; 
      } 

      yield return arr; 
     } 
    } 

    public int Extent 
    { 
     get { return _extent; } 
    } 

    public void UpdateExtent(int extent) 
    { 
     _extent = extent; 
    } 
} 

}

综上所述我接收串[]的项,用于通过VirtualCollection特定的范围。

什么,我试图现在是Virtualaize为好,由给定的程度在运行时产生的 我列列,这是附加属性的回调, 在一个静态类DataGridBuilderUtil

CS完成:

for (int i = 0; i < _iterator.Extent; i++) 
    { 
     _dataGrid.Columns.Add(CreateColumn(i)); 
    } 

    private static DataGridColumn CreateColumn(int i) 
    { 
     var column = new DataGridTextColumn(); 
     column.Header = "View - " + (i + 1); 
     column.Binding = new Binding("[" + i + "]"); 
     return column; 
    } 

在DataGridBuilderUtil我还附上DataGrid的ScrollViewer中ScrollChanged事件, 当一个水平范围发生变化:

1)我添加一个新的列。

2)我更新了Iterators Extent以容纳另一列。

3)我重新滚动垂直同样的位置,这使得我的It​​emsSource(VirtualCollection) 从IList中派生查询它的指数,并再次请求当前页面(与我旗的帮助下 IsDefferedLoadPageRequired)

private static void OnScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     if(e.HorizontalChange > 0.0) 
     {     
      // add column (1) 
     _dataGrid.Columns.Add(CreateColumn(_dataGrid.Columns.Count));    

      // Update the Extent (2) 
      _iterator.UpdateExtent(_dataGrid.Columns.Count);    

      // Makes the VirtualCollection request the current page again. (3) 
      _collection.IsDefferedLoadPageRequired = true;        
      _scrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset); 
     } 
    } 

所以现在VirtualCollection

public T this[int index] 
    { 
     get 
     { 
      .... 
      int pageIndex = index/PageSize; 
      RequestPage(pageIndex);     
      .... 
     }    
    } 

其描述查询ItemsProvider内:

public IList<T[]> FetchRange(int startIndex, int count) 
    { 
     return _iterator.Skip(startIndex).Take(count).ToList(); 
    } 

哪些问题需要迭代器,请记住我们的Extent已增加以容纳另一列。

public IEnumerator<T[]> GetEnumerator() 
    { 
     for (int i = 0; i < _arrayItemLength; i++) 
     { 
      T[] arr = new T[_extent]; 

      for (int j = 0; j < _extent; j++) 
      { 
       arr[j] = _items[j][i]; 
      } 

      yield return arr; 
     } 
    } 

所以,现在我有一个字符串[]项目的这是递增串[20]项目现在串[21] 我的横向数据虚拟化的工作。

的问题是,我的细胞中,以这种方式结合的:(从上面CreateColumn方法)

column.Binding = new Binding("[" + i + "]"); 

在一个新的列具有的结合误差,在每个单元(结合的中其装载的收集工作正常时产生的原始列:

 System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'String') from '' (type 'String[]').  BindingExpression:Path=[20]; DataItem='String[]' (HashCode=32127640); 
     target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')  ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. 
     Parameter name: index' 

我认为这是与事实,当我的列上创建数组项该行 确实没有做t包含该索引,或者我也尝试在数组更新后创建列。

结果相同。

这里最大的问题是,为什么不绑定工作,以及如何刷新绑定?

此外,我设置DataGrid.EnableColumnVirtualization = True将这一切(如果绑定将工作)。

编辑:

Iv'e还试图创建列集合被更新后:

 _collection.LoadCompletedEvent += OnLoadCompleted; // VirualCollection event after page is loaded. 

    private static void OnLoadCompleted(object sender, EventArgs e) 
    { 
     _dataGrid.Columns.Add(CreateColumn(_dataGrid.Columns.Count)); 
    } 

    private static void OnScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     if(e.HorizontalChange > 0.0) 
     {     
      // Update the Extent 
      _iterator.UpdateExtent(_dataGrid.Columns.Count+1); 

      // Makes the VirtualCollection request the current page again. 
      _collection.IsLoadPageRequired = true;        
      _scrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset); 
     } 
    } 

的onLoadComplete的VirtualCollection重新加载当前页面后上升。

知道该错误是否总是被抛出或者只有当您开始滚动时才会很有趣。然后绑定可能会要求索引,因为您尚未在VirtualCollection中实现该索引。

虽然说实话我有一种感觉,你正在使用索引器的绑定路径语法错误。

看看这些链接:

http://msdn.microsoft.com/en-us/library/ms742451.aspx

http://msdn.microsoft.com/en-us/library/system.windows.data.binding.path.aspx

作为例子:

<Binding Path="[key]" .../> 

关键必须是类型化指数字典或哈希表,或数组的整数索引。此外,键的值必须是可直接绑定到应用该属性的类型。例如,包含字符串键和字符串值的散列表可以用这种方式绑定到TextBox的Text。

意思是如果你的索引器是整数类型的,你需要在你的XAML中使用类似的东西。

<Binding Path="[(sys:Int32)42,(sys:Int32)24]"... /> 

我不知道你为什么手动创建你的绑定。你可以在xaml中做到这一点,coudnt你? :)

+0

只有当我开始滚动 –

+0

,关键是在数组的索引,每行的DataContext的是一个字符串 –

+0

那么它可能是第一种情况的数组,你还没有获取的数据尚未虽然当时的细胞结合正在更新。你在使用虚拟化的回收模式吗? –