[英]WPF DataGrid: Issue regarding virtualization of selected cells outside of visible area
我的DataGrid
处理大量数据(平均高达4万行),所以我需要虚拟化很多。
在某种程度上,我需要在某一列中选择一大堆(如果不是全部)单元格来共同更改它们的值。 对于任何感兴趣的人,我通过处理列标题(通常对列进行排序)并调用以下方法来实现此目的:
private void SelectColumn(object sender, DataGridSortingEventArgs e)
{
if (MyDataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
DataGridColumn column = e.Column;
if (e.Column != null)
{
MyDataGrid.UnselectAllCells();
for (int i = 0; i < MyDataGrid.Items.Count; i++)
{
MyDataGrid.SelectedCells.Add(new DataGridCellInfo(MyDataGrid.Items[i], column));
}
// Set the first cell into editing mode
MyDataGrid.CurrentCell = MyDataGrid.SelectedCells[0];
}
}
}
编辑:对不起,我差点忘了添加我的代码来设置所选单元格的值...:
private void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (MyDataGrid.SelectedCells.Count > 1)
{ // More than 1 cell are selected
if (e.EditingElement.GetType() == typeof(TextBox))
{ // The cell being edited is of type TextBox
string value = ((TextBox)e.EditingElement).Text;
foreach (DataGridCellInfo cellInfo in MyDataGrid.SelectedCells)
{
DataGridCell gridCell = TryToFindGridCell(MyDataGrid, cellInfo);
if (gridCell != null) gridCell.Content = value; // ((TextBox)e.EditingElement).Text returns the Text in the cell sending DataGridCellEditEndingEventArgs e
}
}
}
}
static DataGridCell TryToFindGridCell(DataGrid grid, DataGridCellInfo cellInfo)
{
DataGridCell result = null;
DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(cellInfo.Item);
if (row != null)
{
int columnIndex = grid.Columns.IndexOf(cellInfo.Column);
if (columnIndex > -1)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
result = presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;
}
}
return result;
}
如果所有选定的单元格都在GUI的可见区域内,则此方法非常有效。 因为外面的一切(有几行作为缓冲区)正在虚拟化,但是我遇到了问题。 虚拟行并未真正选择,可见区域外的任何单元格都不会随可见区域一起更改其值。
任何人都可以指导我更好的方法吗? 是的,我需要处理这些数据,抱歉。 ;)
我最近遇到了与WPF数据网格相同的问题。 这太慢了。 我认为这是因为datagridrow对象对于这个数据量而言太过膨胀。
在我的情况下,我有一个非常相似的结果我必须处理。 我通过完全削减数据网格来解决它。 我希望你的#列是不变的,因为如果不是这样的话,那将是一种痛苦(读:我不知道如何:))以实现这种方式... anyhoo ...
创建一个类并为数据表中的每个列创建一个属性
class TableItem
{
public string Column1 { get; set: }
public string Column2 { get; set; }
}
等等....
无论您从何处加载数据,都要遍历数据表/ etc并将列添加到viewmodel中的ObservableCollection对象。
for (int = 0; i < yourDataTable.Rows.Count; i++)
{
DataRow row = yourDataTable.Rows[i];
TableItem ti = new TableItem
{
Column1 = row["Column1Name"].ToString(),
Column2 = row["Column2Name"].ToString()
}
yourObservableCollection.Add(ti);
}
ObservableCollectionInViewModel = yourObservableCollection;
然后创建一个ListView,并为它提供所需的许多列。 将ListView绑定到我们刚刚创建的viewmodel中的ObservableCollection,然后使用DisplayMemberBinding将每个列绑定到TableItem对象的相应属性:
<ListView x:Name="lstGridWOResourceHogging" SelectionMode="Extended" ItemsSource="{Binding ObservableCollecitonInViewModel, IsAsync="True"
VirtualizingPanel.IsVirtualizing="False">
<ListView.View>
<GridView>
<GridViewColumn Header="Column1Name" DisplayMemberBinding="{Binding Column1}"/>
<GridViewColumn Header="Column2Name" DisplayMemberBinding="{Binding Column2}"/>
</GridView>
</ListView.View>
</ListView>
通过这种方式,您可以关闭虚拟化,因为它不像datagrid的对象那么胖,性能要好得多。 现在,在没有虚拟化的情况下,您选择的内容确实被选中,您可以通过理智来迭代它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.