Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wpf RowDetailsTemplate focus

Tags:

wpf

datagrid

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?

like image 247
seanzi Avatar asked May 09 '12 15:05

seanzi


2 Answers

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.

like image 104
Samuel Avatar answered Nov 05 '22 21:11

Samuel


I found a good solution :D

I have one line of code that solves this problem but 10 lines to describe what is the problem. Here is the solution:

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);

        // to stop RowDetails from eating the first click.
        if (e.Property.Name == "SelectedItem" && CurrentItem == null) CurrentItem = SelectedItem;
    }

AND Find the details here please.

like image 22
Ashi Avatar answered Nov 05 '22 22:11

Ashi