You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

WPF DataGrid取消编辑后无法选中单元格全部内容的问题排查

WPF DataGrid单元格无法全选内容的问题修复

问题描述

我有一个WPF DataGrid,正在处理ViewModel中不存在对应项的场景:此时会显示错误提示,并尝试将焦点返回至触发错误的单元格以允许重新编辑。但目前单元格虽保留焦点,却无法选中全部内容,以下是我的代码:

if (!_viewModel.ItemExists(codPro))
{
    MessageBox.Show(
        "O item não existe na tabela de itens.",
        "Erro",
        MessageBoxButton.OK,
        MessageBoxImage.Error
    );
    e.Cancel = true;

    (sender as DataGrid).Dispatcher.BeginInvoke((Action)(() =>
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid != null)
        {
            dataGrid.SelectedCells.Clear();
            dataGrid.SelectedCells.Add(new DataGridCellInfo(e.Row.Item, e.Column));
            dataGrid.CurrentCell = new DataGridCellInfo(e.Row.Item, e.Column);
            dataGrid.BeginEdit();

            var cellContent = dataGrid.Columns[e.Column.DisplayIndex].GetCellContent(e.Row);
            if (cellContent != null)
            {
                var cell = cellContent.Parent as DataGridCell;
                if (cell != null)
                {
                    cell.Focus();
                    var textBox = cellContent as TextBox;
                    if (textBox != null)
                    {
                        textBox.SelectAll();
                    }
                }
            }
        }
    }));

    return;
}

问题原因

核心问题在于SelectAll的执行时机和冗余操作干扰:

  1. BeginEdit后直接调用SelectAll,WPF内部的编辑控件初始化逻辑会覆盖你的选择操作。
  2. 默认的Dispatcher.BeginInvoke优先级过高,导致在TextBox完全进入编辑状态前执行了SelectAll,操作无效。
  3. 重复设置SelectedCellsCurrentCell反而打乱了DataGrid的默认焦点管理逻辑。

修复方案

调整代码逻辑,确保SelectAll在控件完全就绪后执行,同时简化不必要的操作:

if (!_viewModel.ItemExists(codPro))
{
    MessageBox.Show(
        "该项目不存在于项目表中。",
        "错误",
        MessageBoxButton.OK,
        MessageBoxImage.Error
    );
    e.Cancel = true;

    var dataGrid = sender as DataGrid;
    if (dataGrid != null)
    {
        // 使用Input优先级确保在UI输入阶段执行,此时TextBox已完全初始化
        dataGrid.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)(() =>
        {
            dataGrid.BeginEdit();
            // 直接通过e.Column获取单元格内容,无需通过DisplayIndex查找
            var cellContent = e.Column.GetCellContent(e.Row);
            if (cellContent is TextBox textBox)
            {
                textBox.Focus();
                textBox.SelectAll();
            }
        }));
    }

    return;
}

关键修改点

  • 移除冗余的SelectedCellsCurrentCell操作:e.Cancel=true已经会保留当前单元格的编辑状态和焦点,无需重复设置。
  • 调整Dispatcher优先级为Input:确保代码在UI线程处理输入的阶段执行,此时TextBox已完成编辑状态的初始化。
  • 简化单元格内容获取:直接使用e.Column.GetCellContent(e.Row),避免通过列索引查找可能带来的错误。
  • 简化类型判断:使用is操作符直接转换TextBox,代码更简洁可靠。

内容的提问来源于stack exchange,提问作者shiblabi

火山引擎 最新活动