C# WPF数据网格列虚拟化

C# WPF数据网格列虚拟化,c#,wpf,datagrid,celltemplate,data-virtualization,C#,Wpf,Datagrid,Celltemplate,Data Virtualization,我正在尝试在我的DataGrid上执行水平虚拟化。 我的收藏类型为: List<string[]> 现在在VirtualCollection中 public T this[int index] { get { .... int pageIndex = index / PageSize; RequestPage(pageIndex);

我正在尝试在我的DataGrid上执行水平虚拟化。 我的收藏类型为:

   List<string[]>
现在在VirtualCollection中

    public T this[int index]
    {
        get
        {
            ....
            int pageIndex = index / PageSize;
            RequestPage(pageIndex);                
            ....
        }             
     }
这需要项目提供商:

    public IList<T[]> FetchRange(int startIndex, int count)
    {
        return _iterator.Skip(startIndex).Take(count).ToList();
    }
在新列中的每个单元格中出现绑定错误(绑定位于加载集合时生成的原始列中):

      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'
我认为这与以下事实有关:当我的列被创建时,该行的数组项 不包含该索引,或者我也尝试在更新数组后创建列

结果是一样的

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

此外,我将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);
        }
    }

在VirtualCollection重新加载当前页面后,将引发OnLoadComplete。

很有意思的是,是否总是抛出该错误,还是仅在您开始滚动时才抛出该错误。然后绑定可能会要求索引,因为您尚未在VirtualCollection中意识到该索引,所以该索引可能还不可用

虽然说实话,我感觉您在索引器中使用绑定路径语法是错误的

看看这些链接:

例如:

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

键必须是字典或哈希表的类型化索引,或数组的整数索引。此外,键的值必须是可直接绑定到应用它的属性的类型。例如,包含字符串键和字符串值的哈希表可以通过这种方式绑定到文本框的文本

也就是说,如果索引器是integer类型,那么在XAML中需要类似的东西

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


我不知道你为什么要手动创建绑定。你可以在xaml中这样做,对吗?:)

只有当我开始滚动并且键是数组中的索引时,每行的DataContext是一个字符串数组。这可能是第一种情况,尽管在更新单元格绑定时,你还没有获取数据。你在使用虚拟化的回收模式吗?我实际上没有使用任何模式,有人猜测这是标准的回收模式,仅供参考,Iv'e也尝试在更新集合之前创建列。首先你获取新数据,然后你应该创建绑定。创建绑定时,它会尝试设置值。在获取新数据之前创建绑定时,将出现错误。从逻辑上讲,不是吗
    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;
        }
    }
 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'
     _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);
        }
    }
<Binding Path="[key]" .../>
<Binding Path="[(sys:Int32)42,(sys:Int32)24]"... />