Nate Zaugg
Nate Zaugg

Reputation: 4218

WPF DataGrid Hide RowDetails or Unselect Row

I have a DataGrid who's RowDetails is set to show when selected (RowDetailsVisibilityMode="VisibleWhenSelected"). Now I want to be able to get rid of it! I put a close button on the row details with this code:

private void Button_Click(object sender, RoutedEventArgs e)
  {
   e.Handled = true;
   Button button = sender as Button;
   DataGridRow row = button.FindAncestor<DataGridRow>();

   row.DetailsVisibility = Visibility.Collapsed;
  }

That code gets me 90% there, but once the row details is collapsed for a given row it will not appear the next time that row is selected.

Upvotes: 12

Views: 19975

Answers (7)

ΩmegaMan
ΩmegaMan

Reputation: 31721

Make sure your datagrid has a name such as

<DataGrid x:Name="dgPrimary"
          ...> 

Place a button in the row template such as

<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <Button Content="X" Click="Button_Click" Width="20"/>
         ....

Then in the codebehind simply set the datagrid's selected index to -1

private void Button_Click(object sender, RoutedEventArgs e)
{
    dgPrimary.SelectedIndex = -1;
}

Upvotes: 0

Anderson
Anderson

Reputation: 81

You can implement this with the following code in XAML:

<WpfToolkit:DataGrid Name="dgSysthetic" ItemsSource="{Binding}" 
    AutoGenerateColumns="True"      
    SelectionMode="Extended"
    RowDetailsVisibilityMode="Collapsed"
    CanUserAddRows="False" CanUserDeleteRows="False"
    CanUserResizeRows="False" CanUserSortColumns="False"
    RowHeaderWidth="20" RowHeight="25">
    <WpfToolkit:DataGrid.RowHeaderTemplate>
        <DataTemplate>
            <Button Name="btnHideRow" Click="btnHideDetails_Click" FontSize="5">></Button>
        </DataTemplate>
    </WpfToolkit:DataGrid.RowHeaderTemplate>
    <WpfToolkit:DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <WpfToolkit:DataGrid Name="dgAnalytical" ItemsSource="{Binding}" AutoGenerateColumns="True"/>                 
        </DataTemplate>
    </WpfToolkit:DataGrid.RowDetailsTemplate>        
</WpfToolkit:DataGrid>

See the button inside RowHeaderTemplate.

In your C# code you would do this:

private void btnHideDetails_Click(object sender, RoutedEventArgs e) 
    { 
        DependencyObject obj = (DependencyObject)e.OriginalSource; 
        while (!(obj is DataGridRow) && obj != null) obj = VisualTreeHelper.GetParent(obj);

        if (obj is DataGridRow)
        {
            if ((obj as DataGridRow).DetailsVisibility == Visibility.Visible)
            {
                (obj as DataGridRow).DetailsVisibility = Visibility.Collapsed;
            }
            else
            {
                (obj as DataGridRow).DetailsVisibility = Visibility.Visible;
            }
        }                
    }

This worked very well for me.

Upvotes: 8

Prethen
Prethen

Reputation: 277

Try this (adding the PreviewMouseDown event to your DataGrid in XAML):

 private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        DataGrid grid = sender as DataGrid;

        if (grid != null)
        {
            FrameworkElement element = e.OriginalSource as FrameworkElement;

            if (element?.DataContext is FixedIncomeOrder)
            {
                if (grid.SelectedItem == (FixedIncomeOrder) ((FrameworkElement) e.OriginalSource).DataContext)
                {
                    grid.SelectedIndex = -1;
                    e.Handled = true;
                }
            }
        }
    }

Upvotes: 0

T. Webster
T. Webster

Reputation: 10109

Try setting a Style on the Button with Setters that set the Button's Command, CommandParameter properties. You'll need to create your a class that inplements ICommand and include it as a StaticResource in XAML. Here I used the DataGridRowHeader as a button instead of a button within row details.

     <local:DeselectRowCommand x:Key='deselectCommand' />
            <Setter Property='Command' Value='{StaticResource deselectCommand}' />
                <Setter Property='CommandParameter' 
    Value='{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
AncestorType=wpf:DataGridRow}}' />

In the command's Execute method you can get the DataGridRow from the command parameter and apply whatever methods you need to.

At least this way you can share this Style or base others off of it and re-use the ICommand for your other DataGrids, and also less event handling.

You can see a working example in this Silverlight-to-WPF DataGrid open-source project.

Upvotes: 1

Jason N
Jason N

Reputation: 151

try adding row.DetailsVisibility = Visibility.Visible; on the RowDetailsVisibilityChanged event.

Upvotes: 1

Burrito
Burrito

Reputation: 31

you can put this as your buttons click event, it walks up the tree finds the datarow and sets the details where needed.

DependencyObject dep = (DependencyObject)e.OriginalSource;
        while ((dep != null) && !(dep is DataGridRow))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }
        if (dep != null && dep is DataGridRow)
        {
            DataGridRow row = dep as DataGridRow;
            if (row.DetailsVisibility == Visibility.Collapsed)
            {
                row.DetailsVisibility = Visibility.Visible;
            }
            else
            {
                row.DetailsVisibility = Visibility.Collapsed;
            }
        }

Upvotes: 3

Lawrence P. Kelley
Lawrence P. Kelley

Reputation: 4326

I've run into this too. Here's a solution:

Keep that button in the RowDetails and change its code a little. Rather than focusing on the individual row's visibility, set the DataGrid's SelectedIndex property to -1 (none selected).

DataGrid1.SelectedIndex = -1;

Since your RowDetailsVisibilityMode is VisibleWhenSelected, the DataGrid will collapse/hide any expanded RowDetails. This works well when the SelectionMode is Single.

Upvotes: 14

Related Questions