Reputation: 105
I have nearly googled myself to death on this one. I see a lot of solutions to my problem, but none of them are working... I can only assume it is because I am nesting datagrids with checkboxes at the center. Right now my app takes two clicks to change the check state of a checkbox. I assume the first click is to get focus on the appropriate row? or cell and the second click activates the check state change.
Here is my XAML:
<Grid>
<DockPanel ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" VirtualizingPanel.IsContainerVirtualizable="True" >
<TextBox x:Name="textBoxSearch" DockPanel.Dock="Top" Margin="10" TextChanged="TxtFilter_TextChanged" Height="25" MinWidth="250" HorizontalAlignment="Stretch"/>
<DataGrid x:Name="objDatagrid" ItemsSource="{Binding DataView}" CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False"
HeadersVisibility="None" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDetailsVisibilityMode="Visible"
VirtualizingPanel.VirtualizationMode="Recycling">
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander Margin="15 0 15 0" IsExpanded="True" HorizontalAlignment="Stretch">
<Expander.Header>
<!-- Control for the expander header text -->
<custom:HighlightTextBlock Text="{Binding Path=Name}"
HighlightPhrase="{Binding ElementName=textBoxSearch, Path=Text}"
HighlightBrush="Lime"/>
</Expander.Header>
<ItemsPresenter HorizontalAlignment="Stretch" />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- Question Container Textblock. -->
<custom:HighlightTextBlock Text="{Binding QuestionText}" FontWeight="Bold"
HighlightPhrase="{Binding ElementName=textBoxSearch, Path=Text}"
HighlightBrush="Lime"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid x:Name="objInnerDatagrid" ItemsSource="{Binding Answers}" CanUserAddRows="False" CanUserDeleteRows="False"
HeadersVisibility="None" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<CheckBox DockPanel.Dock="Top" Checked="CheckBox_Checked" Unchecked="CheckBox_Checked" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<CheckBox.Content>
<!-- Answer Checkbox Content : Textblock. -->
<custom:HighlightTextBlock Text="{Binding AnswerText}"
HighlightPhrase="{Binding ElementName=textBoxSearch, Path=Text}" HighlightBrush="Lime"/>
</CheckBox.Content>
</CheckBox>
<custom:TestUC Margin="20,10,0,0" HorizontalAlignment="Stretch" Visibility="Collapsed" x:Name="SubQuestionUserControl"/>
</DockPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</DockPanel>
</Grid>
I have tried setting styles:
<UserControl.Resources>
<vm:StringToVisibilityConverter x:Key="StringToVisibilityConverter"/>
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
<!--<Style TargetType="custom:DataGridWithNavigation" BasedOn="{StaticResource {x:Type DataGrid}}"/>-->
<!--<Style TargetType="{x:Type DataGridCell}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" />
<EventSetter Event="PreviewTextInput" Handler="DataGridCell_PreviewTextInput" />
</Style>-->
<!--<Style x:Key="dataGridStyle" TargetType="{x:Type DataGridCell}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
</Style>-->
<!--<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="MouseEnter" Handler="DataGridCell_PreviewMouseLeftButtonDown"></EventSetter>
</Style>-->
<!--<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>-->
<!--<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsReadOnly" Value="False" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="IsEditing" Value="True" />
</MultiTrigger>
</Style.Triggers>
</Style>-->
</UserControl.Resources>
I no longer have the code behind for any of those associated events to show unfortunately.
I have also tried using someone's custom datagrid class references here: https://stackoverflow.com/a/4827377/5807358
This custom class got me the closest. In fact it worked great... until I needed to un-check that checkbox (located in the inner datagrid). There was no way of changing the check state of an already checked box without first switching to another Row of the main datagrid and then back. I fiddled with trying to customize that class even further to get what I wanted but came up short.
I should also note that I've tried every solution on the stackoverflow link posted above.
Has anyone come across this before? I can post my code-behind if anyone thinks its relevant.
Thanks
Upvotes: 2
Views: 1630
Reputation: 105
I found my answer here! : http://blog.ditran.net/wpf-datagrid-rowdetailstemplate-double-click-focus-fix/
I'll post the code in case the post ever gets removed:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="SelectRowDetailSection"/>
</Style>
</DataGrid.RowStyle>
Event Handler:
void SelectRowDetailSection(object sender, MouseButtonEventArgs e)
{
var row = sender as DataGridRow;
if (row != null)
{
row.Focusable = true;
row.Focus();
// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;
// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
// Change keyboard focus.
if (elementWithFocus != null)
{
elementWithFocus.MoveFocus(request);
}
}
}
The style above needed to be added within the outter . When I added it to the UserControl.Resources section, it did nothing. I should note that I had to add an additional style to the DataGridRow. With the above code when a row was selected, the row header disappeared. This is likely caused by something on my end. I am using mahapps.metro to style my windows. I bet that might be the culprit.
Upvotes: 3