Reselect row after refresh

Sometime I feel some feature is missing but I did not articulated it yet. For example, if I press the "Refresh" button then all the value is refreshed in the DataGrid. It also meant that row selection was cleared.


Before Refresh.


After Refresh.

This was not a major issue because the "Refresh" button is used rarely and I knew that if the ItemsSource of the DataGrid is repopulated then it is natural that there is no SelectedItem

Later I realized, users may miss the reselect row feature, especially if the "Auto refresh" option is turned on. We need a property to store the id of previously selected row.

int? IdOfThePreviouslySelectedRow { get; set; }

This property is nullable because it has no value if go to a new page.

If CopyDataFromTableVmToDbAsync is called then the new property must be set, so we remember the Id of the selected row.

if (SelectedRow is not null)
   IdOfThePreviouslySelectedRow = (SelectedRow as IHasId).Id;


If 
CopyDataFromDbToTableVmAsync is called then the new property is used to reselect the previously selected row.

if (IdOfThePreviouslySelectedRow is not null)
{
  var previouslySelectedRow = DisplayedRows.FirstOrDefault(e => e.Id == IdOfThePreviouslySelectedRow);
  if (previouslySelectedRow is not null)
     SelectedRow = previouslySelectedRow;
  previouslySelectedRow = null;
}
else
  selectedRow = null;

The logic is good, every edge case is handled, but the row is not reselected. 

The problem was that the default Mode of the SelectedItem seems to be OneWayToSource. It means the change only goes from the view to view model but not the other way around. I don't understand why is this, it does not logical for me but at least it was clear what to change.

SelectedItem="{Binding PagerViewModel.SelectedRow, Mode=TwoWay}"



The mode was fixed but there was still some problem after the "Refresh" button is used. I was thinking and thinking when I realized the reselection works but the DataGrid is not in focus, so instead of the blue background the light gray background in row six indicated the selection. 

public class DataGridGetsFocusAfterSelectionChangedBehavior : Behavior<DataGrid>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectionChanged += OnSelectionChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.SelectionChanged -= OnSelectionChanged;
    }

    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var dataGrid = AssociatedObject;
        if (dataGrid.SelectedItem is null)
            return;
        dataGrid.Dispatcher.BeginInvoke(() => dataGrid.Focus());
    }
}

Setting the focus from the View model is not easy because the View model does not know about the DataGrid.  The Behavior above can help us. Whenever a selection is changed, for example from code, then the DataGrid is focused.



Previous Post Next Post

Contact Form