wpf中datagrid表格控件中单元格样式、颜色串行问题分析及解决办法

        昨天在使用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;
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值