[英]How to focus cell on new row in WPF DataGrid
.Net 4 WPF DataGrid MVVM
用户单击添加按钮触发视图模型上的命令。 在 viewmodel 命令执行中,我将一个新对象添加到网格绑定到的视图模型的视图集合中。 新行确实出现在我的网格中。 但是,我还想将焦点发送到该新行中的第一个可编辑单元格。
我什至“欺骗”了 mvvm,在我的视图模型上添加了一个视图监听的事件,以了解何时关注新行。
我已经搜索过,但没有运气。 当我遇到这个时,我充满希望:
这导致
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/63974f4f-d9ee-45af-8499-42f29cbc22ae
但是其他人反映的问题却没有人回答,就是如何处理网格的虚拟化行为。 新添加的行尚未创建。 因此 GetCells 调用经常失败。 如果需要 ScrollIntoView,则失败的可能性更大。
我已经吸引了大量事件,包括 LoadingRow 和 RequestBringIntoView ,但没有运气。 根据我挂钩的事件,我设法能够获得对单元格的引用。 但是后来我收到错误消息“在生成内容时无法调用 StartAt”。 但是我检查了 ItemContainerGenerator 的状态,当我调用单元格的 BeginEdit 时它是 ContainersGenerated。
这是以编程方式将焦点设置到特定单元格的一种方法:
DataGridCell cell = GetCell(rowIndex, colIndex);
cell.Focus;
有关 GetCell() 的更多信息,请参阅以下文章。
这似乎对我有用:
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
private void SetFocusOnNewRow(DataGrid theDataGrid, Int32 columnIndex)
{
theDataGrid.UnselectAll();
theDataGrid.UpdateLayout();
Int32 newRowIndex = theDataGrid.Items.Count - 1;
theDataGrid.ScrollIntoView(theDataGrid.Items[newRowIndex]);
DataGridRow newDataGridRow = theDataGrid.ItemContainerGenerator.ContainerFromIndex(newRowIndex) as DataGridRow;
DataGridCellsPresenter newDataGridCellsPresenter = GetVisualChild<DataGridCellsPresenter>(newDataGridRow);
if (newDataGridCellsPresenter != null)
{
DataGridCell newDataGridCell = newDataGridCellsPresenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;
if (newDataGridCell != null)
newDataGridCell.Focus();
}
}
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;
}
这对我来说是工作:
private void button_Click(object sender, RoutedEventArgs e)
{
//Scroll to the last row
var border = VisualTreeHelper.GetChild(dataGrid, 0) as Decorator;
if (border != null)
{
var scroll = border.Child as ScrollViewer;
if (scroll != null) scroll.ScrollToEnd();
}
//Edit the first cell of the last row
int lastRow = dataGrid.Items.Count - 1;
DataGridCell cell = GetCell(lastRow, 0);
cell.Focus();
dataGrid.BeginEdit();
}
public DataGridCell GetCell(int row, int column)
{
DataGridRow rowContainer = GetRow(row);
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
// try to get the cell but it may possibly be virtualized
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
// now try to bring into view and retreive the cell
dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return cell;
}
return null;
}
public DataGridRow GetRow(int index)
{
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
if (row == null)
{
// may be virtualized, bring into view and try again
dataGrid.ScrollIntoView(dataGrid.Items[index]);
row = (DataGridRow)dataGrid.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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.