Berryl
Berryl

Reputation: 12833

DataGrid select last cell programmatically

When the DataGrid below gets the focus for the first time and only the first time (ie, after some other control has had the focus), the last row, 2nd column should be focused and in edit.

enter image description here

I added a handler for the DataGrid.GotFocus, but it's complicated code and not getting the result above.

Anyone got an elegant, bullet proof solution?


I made tiny modifications to the code

  1. the sender should always be the grid I want, so I just used that instead of relying on a name
  2. When the SelectionUnit is FullRow, as my grid was before I changed it to CellOrRowHeader you apparently can't call SelectedCells.Clear()

Code below:

private void OnDataGridKeyboardGotFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    var dg = sender as DataGrid;
    if (_hasHadInitialFocus) return;

    var rowIndex = dg.Items.Count - 2;
    if (rowIndex >= 0 && dg.Columns.Count - 1 >= 0)
    {
        var column = dg.Columns[dg.Columns.Count - 1];
        var item = dg.Items[rowIndex];
        var dataGridCellInfo = new DataGridCellInfo(item, column);

        if (dg.SelectionUnit != DataGridSelectionUnit.FullRow) {
            dg.SelectedCells.Clear();
            dg.SelectedCells.Add(dataGridCellInfo);
        }
        else {
            var row = dg.GetRow(rowIndex);
            row.IsSelected = true;
        }

        dg.CurrentCell = dataGridCellInfo;
        dg.BeginEdit();
    }

    _hasHadInitialFocus = true;
}

New Question

I want to repeat the selection when the focus goes to another control in the window and then back to the grid. I thought I could turn that _hasHadInitialFocus latch to false in a LostFocus event, but the code below is firing on cell changes. Do you know how I should be trapping the lost focus event better, and do you agree that is the place to turn the latch off?

    private void DataGridLostFocus(object sender, RoutedEventArgs e) {
        _hasHadInitialFocus = false;
    }

Upvotes: 0

Views: 4104

Answers (1)

Phil
Phil

Reputation: 42991

You may have to fiddle with the offsets depending on whether there's an new item row visible or not, but this works for me.

    private bool _hasHadInitialFocus;

    private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!_hasHadInitialFocus)
        {
            if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
            {
                var dataGridCellInfo = new DataGridCellInfo(
                    dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);

                dataGrid.SelectedCells.Clear();
                dataGrid.SelectedCells.Add(dataGridCellInfo);
                dataGrid.CurrentCell = dataGridCellInfo;
                dataGrid.BeginEdit();
            }

            _hasHadInitialFocus = true;
        }
    }

I noticed that clicking into the grid leaves one cell selected and the target cell in edit mode. A solution to this if required is:

    private void DataGridGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        EditCell();
    }

    private void PreviewMouseLBDown(object sender, MouseButtonEventArgs e)
    {
        if (!_hasHadInitialFocus)
        {
            e.Handled = true;
            EditCell();
        }
    }

    private void EditCell()
    {
        if (!_hasHadInitialFocus)
        {
            if (dataGrid.Items.Count - 2 >= 0 && dataGrid.Columns.Count - 1 >= 0)
            {
                var dataGridCellInfo = new DataGridCellInfo(
                    dataGrid.Items[dataGrid.Items.Count - 2], dataGrid.Columns[dataGrid.Columns.Count - 1]);

                dataGrid.SelectedCells.Clear();
                dataGrid.SelectedCells.Add(dataGridCellInfo);
                dataGrid.CurrentCell = dataGridCellInfo;
                dataGrid.BeginEdit();
            }

            _hasHadInitialFocus = true;
        }
    }

Upvotes: 1

Related Questions