Search code examples
wpfdatagrid

wpf RowDetailsTemplate focus


I currently have a datagrid with a rowdetailstemplate which contains another datagrid to show a parent to child relationship. The second grid has a column which contains a button which when clicked displays another dialog.

The first time the details for a row are displayed, the user has to click once in the child grid to gain focus/activate it and then click again to fire the button click event. This only happens the first time a row is shown.

It is like the first click is swallowed by the grid. I have tried capturing the RowDetailsVisibilityChanged event to try and focus the button but it still doesn't seem to have solved the issue.

Any ideas?


Solution

  • I'll answer my own comment and it probably helps others too. The following MSDN entry explains and solves the issue: http://social.msdn.microsoft.com/Forums/vstudio/en-US/2cde5655-4b8d-4a12-8365-bb0e4a93546f/activating-input-controls-inside-datagrids-rowdetailstemplate-with-single-click?forum=wpf

    The problem is that a row details that is always shown requires gaining the focus first. To circumvent that problem a datagrid preview handler is required:

    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}"  BasedOn="{StaticResource {x:Type DataGridRow}}">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="SelectRowDetails"/>
        </Style>
    </DataGrid.RowStyle>
    

    Note: I've extended it as it destroyed my custom DataGridRow Style to inherit the currently used one.

    The handler itself is

    private void SelectRowDetails(object sender, MouseButtonEventArgs e)
    {
        var row = sender as DataGridRow;
        if (row == null)
        {
            return;
        }
        row.Focusable = true;
        row.Focus();
    
        var focusDirection = FocusNavigationDirection.Next;
        var request = new TraversalRequest(focusDirection);
        var elementWithFocus = Keyboard.FocusedElement as UIElement;
        if (elementWithFocus != null)
        {
            elementWithFocus.MoveFocus(request);
        }
    }
    

    It sets the focus to the content of the row details, which solves the click-twice issue.

    Note: This all taken from the MSDN thread, it is not my own solution.