wpf RowDetailsTemplate focus
Asked Answered
J

3

5

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?

Jasminjasmina answered 9/5, 2012 at 15:51 Comment(4)
Does your RowDetails DataGrid have more than one row? If so, do you have the same problem with all of the rows? I suspect you have the same problem as here: https://mcmap.net/q/1526619/-wpf-datagrid-issueNonoccurrence
Ever tried setting "focusEnabled=true" ??Ileus
@Meleak thanks for the suggestion. My datagrid does indeed have more than one row. However the suggestion in the post does not seem to fix my issue. The rowdetails are expanded automatically and the first time a detail is clicked, 2 clicks are required to click on a button contained within. However if I manually cycle the details (close and reshow them) then only one click is required.Jasminjasmina
Did you solved your issue at hand? I've come across this thread with the same problem.Salonika
S
6

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.

Salonika answered 4/2, 2014 at 18:14 Comment(1)
I've literally referenced this answer multiple times over the years (I always forget, then have to search it up and after hours I find this and see that I have already upvoted it). Thanks for sharing this!!! If I could upvote multiple times I would.Iinde
P
1

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.

Popliteal answered 28/4, 2014 at 7:50 Comment(2)
This is one way to do it, though some details would have been helpful ; this solves the problem by deriving a class form DataGrid, then synchronising SelectedItem with CurrentItem every time a property of the grid changes. The effect of this is that the selected item always has focus. the downside of this is that it's tremendously wasteful compared to the other solution.Intramural
well yeah .. saying "THE solution" was so mean :DPopliteal
M
0

This is my first post here, so I cannot comment...

Since this was driving me crazy for a while I wanted to add a line to Samuels answer (which is actually a great solution).

I had the problem, that I could not select items from a ComboBox inside the DetailsView, because the focus was always set to the DataGridRow, so to avoid re-focusing and make the solution more stable, I added the check

if(row.IsKeyboardFocusWithin) return;

So the complete Code looks like this:

private void SelectRowDetails(object sender, MouseButtonEventArgs e)
{
    var row = sender as DataGridRow;
    if (row == null || row.IsKeyboardFocusWithin)
    {
        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);
    }
}
Mcclendon answered 22/4, 2024 at 17:21 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.