在datagridview中选择一个单元格并开始编辑

时间:2014-02-27 17:47:39

标签: c# wpf datagridview cell

我在互联网上看到这个话题很常见,我不明白为什么还没有创建直接选择数据网格视图中的单元格的方法。

我创建了这个类Helper:

using Microsoft.Windows.Controls.Primitives;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;

namespace gestione_magazzino_v4.Classi
{
    static class DataGridViewHelper
    {
        static public DataGridCell GetCell(DataGrid dg, int row, int column)
        {
            DataGridRow rowContainer = GetRow(dg, row);

            if (rowContainer != null)
            {
                DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);  

                DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);  // <<<------ ERROR
                if (cell == null)
                {
                    // now try to bring into view and retreive the cell
                    dg.ScrollIntoView(rowContainer, dg.Columns[column]);
                    cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
                }
                return cell;
            }
            return null;
        }

        static public DataGridRow GetRow(DataGrid dg, int index)
        {
            DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);
            if (row == null)
            {
                // may be virtualized, bring into view and try again
                dg.ScrollIntoView(dg.Items[index]);
                row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);
            }
            return row;
        }

        static T GetVisualChild<T>(Visual parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null)
                {
                    child = GetVisualChild<T>(v);
                }
                if (child != null)
                {
                    break;
                }
            }
            return child;
        }
    }
}

我使用这样的代码:

DataGridCell cell = DataGridViewHelper.GetCell(datagridview, 0, 2);
if (cell != null)
    cell.Focus();

但是我突然强调了一个错误,特别是我得到 System.NullReferenceException

我不明白缺少什么......在网上有很多例子,但它们都与我所做的相同,我不明白缺少什么!

2 个答案:

答案 0 :(得分:0)

DataGridCellPresenter为null,这是由DataGrid的虚拟化引起的。

假设您有100行,并向下滚动到第[49]行,其中该行是屏幕上最可见的行,对于第0-48行,其DataGridCellPresenter已进行虚拟化(处置)。

DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);  
if(presenter != null)
{
    // Select your cell...
}

如果您在滚动后选择它,则此方案的另一个示例可能是在您首次显示UserControl(或任何形式的视图)时尝试执行此操作。

您必须等待DataGrid加载:

 dataGrid.Loaded += DG_Loaded;


 void DG_Loaded(object sender, System.Windows.RoutedEventArgs e)
 {
        ScrollViewer _sv = GetVisualChild<ScrollViewer>(dataGrid);           
 }

在DataGrid完成加载之前,尚未创建所有VisualTree,包括它是上面显示的最顶级的ScrollViewer。

将GetVisualChild替换为:

 public static T GetVisualChild<T>(DependencyObject depObj) where T : Visual
 {
      if (depObj != null)
      {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                if (child != null && child is T)
                {
                    return (T)child;
                }

                foreach (T childOfChild in GetVisualChild<T>(child))
                {
                    return childOfChild;
                }
            }
       }
       return null;
  }

我认为错误的是,在视觉树下的所有元素都不是Visual的, 例如,沿途的任何面板都不是Visual,因此当您将其转换为Visual时,您将获得null并且永远不会到达DataGridCellPresenter。

答案 1 :(得分:0)

Foud解决方案!!! 问题是使用:

using Microsoft.Windows.Controls.Primitives;

但正确的是:

using System.Windows.Controls.Primitives;