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)我重新滚动垂直同样的位置,这使得我的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重新加载当前页面后上升。
知道该错误是否总是被抛出或者只有当您开始滚动时才会很有趣。然后绑定可能会要求索引,因为您尚未在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你? :)
只有当我开始滚动 –
,关键是在数组的索引,每行的DataContext的是一个字符串 –
那么它可能是第一种情况的数组,你还没有获取的数据尚未虽然当时的细胞结合正在更新。你在使用虚拟化的回收模式吗? –