Reputation: 883
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?
Upvotes: 5
Views: 2932
Reputation: 1
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);
}
}
Upvotes: 0
Reputation: 864
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.
Upvotes: 1
Reputation: 6490
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.
Upvotes: 6