我試圖在我的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)我重新滾動垂直同樣的位置,這使得我的ItemsSource(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重新加載當前頁面後上升。
只有當我開始滾動 –
,關鍵是在數組的索引,每行的DataContext的是一個字符串 –
那麼它可能是第一種情況的數組,你還沒有獲取的數據尚未雖然當時的細胞結合正在更新。你在使用虛擬化的回收模式嗎? –