2013-10-28 119 views
1

我試圖在我的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重新加載當前頁面後上升。

回答

0

知道該錯誤是否總是被拋出或者只有當您開始滾動時纔會很有趣。然後綁定可能會要求索引,因爲您尚未在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

那麼它可能是第一種情況的數組,你還沒有獲取的數據尚未雖然當時的細胞結合正在更新。你在使用虛擬化的回收模式嗎? –