昨天在使用datagrid时,遇到一个问题:通过行和列索引定位到datagrid中的一个单元格,然后修改其前景颜色,发现其他单元格(随机的,没有规则)的颜色也被修改。后来发现这是datagrid中的单元格回收(重用)机制导致。
例如我要修改第3行第5列(即行索引为2,列索引为4),第6行第4列(即行索引为5,列索引为3)的单元格为红色,但实际显示效果如下图所示:


而且表格在多次随机滚动后,原来正确显示颜色的单元格也可能会没了颜色,其他的没有颜色单元格也会随机被改为红色。。
解决办法非常简单:将DataGrid中EnableRowVirtualization和EnableColumnVirtualization两个属性设为False即可,如下图所示:

可通过以下代码进行测试(将EnableRowVirtualization和EnableColumnVirtualization同时设置为true或false对比一下可知):
1. MainWindows.xaml文件:
<Window x:Class="demo_datagrid_cell_recycle_issue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:demo_datagrid_cell_recycle_issue"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid x:Name="ctlDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="False" EnableColumnVirtualization="False"></DataGrid>
</Grid>
</Window>
2. MainWindows.xaml.cs文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace demo_datagrid_cell_recycle_issue
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public SolidColorBrush RedBrush { get; set; } = new SolidColorBrush(Colors.Red);
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// 创建一个100行,5列的表格,单元格的值为1到500
var gridData = new List<List<int>>();
int rowCount = 100;
int columnCount = 5;
for(int rowIndex = 0; rowIndex < rowCount;rowIndex++)
{
var rowData = new List<int>();
for(int columnIndex = 0;columnIndex<columnCount;columnIndex++)
{
var cellValue = rowIndex * columnCount + columnIndex + 1;
rowData.Add(cellValue);
}
gridData.Add(rowData);
}
// 创建对应的表格列
for (int i = 0; i < columnCount; i++)
{
DataGridTextColumn column = new DataGridTextColumn
{
CanUserSort = false,
Binding = new Binding($"[{i}]") // 将绑定到每行的第i列
};
// 将动态生成的列添加到 DataGrid 中
ctlDataGrid.Columns.Add(column);
}
ctlDataGrid.ItemsSource = gridData;
ctlDataGrid.UpdateLayout();
// 待修改颜色的单元格(第一项为行索引,第二项为列索引)
var modifyCellList = new List<Tuple<int, int>>();
modifyCellList.Add(new Tuple<int, int>(2, 4));
modifyCellList.Add(new Tuple<int, int>(5, 3));
// 修改单元格对应的颜色
foreach (var tuple in modifyCellList)
{
var rowIndex = tuple.Item1;
var columnIndex = tuple.Item2;
UpdateCellColor(rowIndex, columnIndex);
}
}
public void UpdateCellColor(int rowIndex, int columnIndex)
{
DataGridRow row = (DataGridRow)ctlDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex);
DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(row);
var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
if (cell != null)
{
cell.Foreground = RedBrush;
}
}
public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
{
return (T)child;
}
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
}
}

2182

被折叠的 条评论
为什么被折叠?



