The answer given by Gauss is the right approach, but with some code, it is clearer:
void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Loaded += Row_Loaded;
}
void Row_Loaded(object sender, RoutedEventArgs e)
{
var row = (DataGridRow) sender;
row.Loaded -= Row_Loaded;
DataGridCell cell = GetCell(dataGrid, row, 0);
if (cell != null) cell.Focus();
dataGrid.BeginEdit();
}
static DataGridCell GetCell(DataGrid dataGrid, DataGridRow row, int column)
{
if (dataGrid == null) throw new ArgumentNullException("dataGrid");
if (row == null) throw new ArgumentNullException("row");
if (column < 0) throw new ArgumentOutOfRangeException("column");
DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(row);
if (presenter == null)
{
row.ApplyTemplate();
presenter = FindVisualChild<DataGridCellsPresenter>(row);
}
if (presenter != null)
{
var cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
if (cell == null)
{
dataGrid.ScrollIntoView(row, dataGrid.Columns[column]);
cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
}
return cell;
}
return null;
}
static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
var visualChild = child as T;
if (visualChild != null)
return visualChild;
var childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
You retrieve the row in the DataGrid.LoadingRow
event, but the cell is not yet available. So you put an handler on the Loaded
event in order to wait for this event to occur and then you can retrieve the cell and put the focus on it.
The handler is removed to avoid a new triggering.
The editing session can also be started with dataGrid.BeginEdit()
.
All of this is in the code-behind, because it belongs to the view.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…