ColleenV
ColleenV

Reputation: 193

Exclude a DataGrid Column from displaying RowDetails

I am teaching myself WPF, LINQ, and MVVM by writing a little tool to parse the CME XML configuration files like the current Production configuration. I have added a DataGridTemplateColumn with a checkbox to the DataGrid that displays the channels so that I can select a few channels that I'm interested in and filter out the rest. The problem is that when I click the checkbox, the RowDetails are displayed.

How can I prevent the click from triggering the display of the RowDetails while still having the "VisibleWhenSelected" behavior if any other column is clicked? Do I need to handle the visibility of the RowDetails myself or is there an easier way?

Here is the updated code with the ToggleButton added as suggested below just in case it is useful to someone else:

<DataGrid x:Name="ChannelListGrid"
          DockPanel.Dock="Top"
          IsReadOnly="True"
          AutoGenerateColumns="False"
          ItemsSource="{Binding Path=ConfigFileXML.Root.Elements[channel]}"
          RowDetailsTemplate="{StaticResource ResourceKey=ConnectionInfoTemplate}"
          IsTextSearchEnabled="True"
          HorizontalAlignment="Left"
          AreRowDetailsFrozen="True"
          RowDetailsVisibilityMode="Collapsed">
    <DataGrid.Columns>
        <DataGridTemplateColumn Width="Auto"
                                CanUserResize="False"
                                CanUserSort="false"
                                CanUserReorder="False">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ToggleButton Click="ToggleRowDetails"
                                  Style="{StaticResource ToggleExpandButtonStyle}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Selected"
                                Width="Auto"
                                CanUserReorder="False"
                                CanUserResize="False">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox Unchecked="ChannelDeselected"
                              Checked="ChannelSelected" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="ID"
                            Binding="{Binding Path=Attribute[id].Value}" />
        <DataGridTextColumn Header="Name"
                            Binding="{Binding Path=Attribute[label].Value}" />
        <DataGridTextColumn Header="Symbol Count"
                            Binding="{Binding Path=Descendants[product].Count}" />
    </DataGrid.Columns>
</DataGrid>

Here are the templates

<DataTemplate x:Key="ConnectionInfoTemplate">
    <DataGrid x:Name="ConnectionListGrid"
              IsReadOnly="True"
              HorizontalAlignment="Left"
              AutoGenerateColumns="False"
              ItemsSource="{Binding Path=Descendants[connection]}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID"
                                Binding="{Binding Path=Attribute[id].Value}" />
            <DataGridTextColumn Header="Type"
                                Binding="{Binding Path=Element[type].Value}" />
            <DataGridTextColumn Header="Protocol"
                                Binding="{Binding Path=Element[protocol].Value}" />
            <DataGridTextColumn Header="Source IP"
                                Binding="{Binding Path=Element[ip].Value}" />
        </DataGrid.Columns>
    </DataGrid>
</DataTemplate>
<SolidColorBrush x:Key="GlyphBrush"
                 Color="#444" />

<Style x:Key="ToggleExpandButtonStyle"
       TargetType="{x:Type ToggleButton}">
    <Setter Property="IsChecked"
            Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Grid Width="15"
                      Height="13"
                      Background="Transparent">
                    <Path x:Name="ExpandPath"
                          HorizontalAlignment="Left"
                          VerticalAlignment="Center"
                          Margin="1,1,1,1"
                          Fill="{StaticResource GlyphBrush}"
                          Data="M 4 0 L 8 4 L 4 8 Z" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked"
                             Value="True">
                        <Setter Property="Data"
                                TargetName="ExpandPath"
                                Value="M 0 4 L 8 4 L 4 8 Z" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Here is the code behind in C#

private T FindAncestor<T>(DependencyObject depObject)
    where T : DependencyObject
{
    var parent = VisualTreeHelper.GetParent(depObject);
    if (parent == null) return null;

    var parentT = parent as T;
    return parentT ?? FindAncestor<T>(parent);
}

private void ToggleRowDetails(object sender, System.Windows.RoutedEventArgs e)
{
    var senderButton = sender as ToggleButton;
    DataGridRow toggledRow = FindAncestor<DataGridRow>(senderButton);

    if (toggledRow != null)
    {
        // If IsChecked is null, use false. If true, make details visible, otherwise collapse the details
        toggledRow.DetailsVisibility = ( senderButton.IsChecked ?? false) ? Visibility.Visible : Visibility.Collapsed;
    }
}

Upvotes: 0

Views: 426

Answers (1)

user3910810
user3910810

Reputation: 234

I had a similar problem and decided to add a toggle button column to manually show the row details.

Style

<SolidColorBrush x:Key="GlyphBrush" Color="#444" />

<Style x:Key="ToggleExpandButtonStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="IsChecked" Value="False"/>
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ToggleButton}">
            <Grid Width="15" Height="13" Background="Transparent">
                <Path x:Name="ExpandPath" HorizontalAlignment="Left" VerticalAlignment="Center" 
                          Margin="1,1,1,1" Fill="{StaticResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
    </Setter>
</Style>

Datagrid column

            <DataGridTemplateColumn Width="Auto" CanUserResize="False" CanUserSort="false" CanUserReorder="False">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                    <ToggleButton Click="ToggleButton_Click" Style="{StaticResource ToggleExpandButtonStyle}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

Click event (in VB)

    Public Shared Sub ToggleButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

    Dim senderButton As Primitives.ToggleButton
    senderButton = CType(sender, Primitives.ToggleButton)
    Dim clickedRow As DataGridRow = CType(GetVisualParent(senderButton, GetType(DataGridRow)), DataGridRow)

    If clickedRow IsNot Nothing Then
        If senderButton.IsChecked Then
            clickedRow.DetailsVisibility = Windows.Visibility.Visible
            clickedRow.BringIntoView()
        Else
            clickedRow.DetailsVisibility = Windows.Visibility.Collapsed
        End If
    End If
  End Sub

Upvotes: 1

Related Questions