Kerwen
Kerwen

Reputation: 552

MVVM DataGrid how to set focus after refresh content

I have a DataGrid like following:

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

I have a timer in ViewModel to refresh the content of DataGrid, after the content is updated, use SelectedRow to reset the current select row.

Check the UI result, the selected row works, but there is no blue background. I guess I miss set focus, but how to implement this?

Upvotes: 0

Views: 971

Answers (1)

mm8
mm8

Reputation: 169280

I guess I miss set focus, but how to implement this?

Programmatically focusing a row in a DataGrid and get the exact same behavior as when you select a row by clicking on it with the mouse requires some effort. Please refer to the following blog post for details.

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

Upvotes: 2

Related Questions