MVVM datagrid刷新内容后如何设置焦点

时间:2018-04-24 07:49:39

标签: c# wpf mvvm datagrid

我有一个如下数据网格:

<DataGrid ItemsSource="{Binding GridSource}" CanUserAddRows="False" AutoGenerateColumns="False" SelectedItem="{Binding SelectedRow, Mode=TwoWay}">
  ...
</DataGrid>

我在ViewModel中有一个计时器来刷新DataGrid的内容,在更新内容后,使用SelectedRow重置当前的选择行。
  检查UI结果,所选行有效,但没有蓝色背景。我想我错过了设置焦点,但如何实现这一点?

1 个答案:

答案 0 :(得分:1)

  

我想我错过了设定焦点,但是如何实现这个?

DataGrid编程方式聚焦行,并获得与使用鼠标单击选择行时完全相同的行为,这需要付出一些努力。有关详细信息,请参阅以下博客文章。

如何在WPF中以编程方式选择和聚焦DataGrid中的行或单元格: https://blog.magnusmontin.net/2013/11/08/how-to-programmatically-select-and-focus-a-row-or-cell-in-a-datagrid-in-wpf/

private static void SelectRowByIndex(DataGrid dataGrid, int rowIndex)
{
    if (!dataGrid.SelectionUnit.Equals(DataGridSelectionUnit.FullRow))
        throw new ArgumentException("The SelectionUnit of the DataGrid must be set to FullRow.");

    if (rowIndex < 0 || rowIndex > (dataGrid.Items.Count - 1))
        throw new ArgumentException(string.Format("{0} is an invalid row index.", rowIndex));

    dataGrid.SelectedItems.Clear();
    /* set the SelectedItem property */
    object item = dataGrid.Items[rowIndex]; // = Product X
    dataGrid.SelectedItem = item;

    DataGridRow row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
    if (row == null)
    {
        /* bring the data item (Product object) into view
         * in case it has been virtualized away */
        dataGrid.ScrollIntoView(item);
        row = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowIndex) as DataGridRow;
    }
    if (row != null)
    {
        DataGridCell cell = GetCell(dataGrid, row, 0);
        if (cell != null)
            cell.Focus();
    }
}

private static DataGridCell GetCell(DataGrid dataGrid, DataGridRow rowContainer, int column)
{
    if (rowContainer != null)
    {
        DataGridCellsPresenter presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
        if (presenter == null)
        {
            /* if the row has been virtualized away, call its ApplyTemplate() method 
             * to build its visual tree in order for the DataGridCellsPresenter
             * and the DataGridCells to be created */
            rowContainer.ApplyTemplate();
            presenter = FindVisualChild<DataGridCellsPresenter>(rowContainer);
        }
        if (presenter != null)
        {
            DataGridCell cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
            if (cell == null)
            {
                /* bring the column into view
                 * in case it has been virtualized away */
                dataGrid.ScrollIntoView(rowContainer, dataGrid.Columns[column]);
                cell = presenter.ItemContainerGenerator.ContainerFromIndex(column) as DataGridCell;
            }
            return cell;
        }
    }
    return null;
}

private 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;
}