Search code examples
c#wpfxamlgridgridsplitter

How to combine GridSplitter and DataGrid, where the DataGrid must have a vertical scrollbar?


I have a xaml, which, more or less, looks as follows (I've filtered on Grid and RowDefinition related entries for showing Grid, DataGrid and RowDefinition entries:

    <Grid x:Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" MaxHeight="60"/>
            <RowDefinition  />
        </Grid.RowDefinitions>
        <Grid x:Name="Grd_Header" Grid.Row ="0" MaxHeight="60">
            <Grid.RowDefinitions>
                <RowDefinition Height="0"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="10"></RowDefinition>
            </Grid.RowDefinitions>
        </Grid>
        <Grid x:Name="Grd_Data" Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"></RowDefinition>
                <RowDefinition Height="10"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid x:Name="Grd_Act" Grid.Row="0" VerticalAlignment="Stretch">
                <Grid.RowDefinitions>
                    <RowDefinition Height="30"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <DataGrid Name="..." Grid.Row="1" Grid.Column="0">
                <telerik:RadBusyIndicator Grid.Row="0" Grid.RowSpan="2" .../>
            </Grid>
            <GridSplitter Grid.Row="1" Height="3" Background="black" HorizontalAlignment="Stretch" />
            <Grid x:Name="Grd_plan" Grid.Row="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"></RowDefinition>
                    <RowDefinition Height="*" MinHeight="50"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Text="planned..." Grid.Row="0" Grid.Column="0"/>
                <DataGrid Grid.Row="1" ...>
                <telerik:RadBusyIndicator Grid.RowSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BusyContent="Loading pallets" IsBusy="{Binding IsLoadingGepandeMatrijsPalletten}" Grid.ColumnSpan="2"/>
            </Grid>
        </Grid>
    </Grid>

At first, the result looks more or less ok:

enter image description here

But from the moment I move the GridSplitter a bit, it goes partially wrong: there is a scrollbar (in green), which must stay present. But the grey space (in the red rectangle): where is that coming from?

(While debugging, I've understood that the grey area belongs to the general view or to the Grid, called MainGrid.)

enter image description here

Before I forget: the Grid.Resources contain different Style tags, like this one for DataGrid:

<Style TargetType="DataGrid">
    <Setter Property="HorizontalAlignment"  Value="Stretch"/>
    <Setter Property="VerticalAlignment"    Value="Stretch"/>
    <Setter Property="AutoGenerateColumns"  Value="False"/>
    <Setter Property="IsReadOnly"           Value="True"/>
    <Setter Property="ColumnWidth"          Value="Auto"/>
    <Setter Property="FontSize"             Value="12"/>
</Style>

Solution

  • I assume that both Grid elements "Grd_Act" and "Grd_plan" are disturbing the layout.
    Their layout is not correct, and elements are not cleanly arranged (redundant properties, wrong values etc.).
    Fixing these layout issues should bring back the expected resize behavior (triggered by the GridSplitter).

    "Grd_Act"

    This Grid has a very odd layout where there are three rows defined for two elements (why not two rows?).
    The arrangement of the elements is wrong too:

    1. The RadBusyIndicator is placed in the first row and spanning two rows.
    2. The DataGrid is placed in the second row, which is also occupied by the spanning RadBusyIndicator - they overlap.
    3. The last row is empty but reserves full space/height (star size). This line is essentially leading to the weird resize behavior. But still the arrangement is wrong too.

    Just make it two rows, one for each element:

    <Grid x:Name="Grd_Act"
          Grid.Row="0">
      <Grid.RowDefinitions>
        <RowDefinition Height="30" />  <!-- Busy indicator row -->
        <RowDefinition Height="*" />   <!-- DataGrid row -->
      </Grid.RowDefinitions>
                   
        <telerik:RadBusyIndicator Grid.Row="0" .../>
        <DataGrid Name="..." Grid.Row="1" />
    </Grid>
    

    "Grd_plan"

    This Grid has correctly defined three rows, one for each element.
    However, the elements are not arranged correctly:

    1. The RadBusyIndicator is placed in the first row - together with the TextBlock (overlap). RadBusyIndicator has a Grid.RowSpan property set to 2, which doesn't make any sense (a typo?). Instead, the element must be placed in the third row.
    2. There are no columns defined, yet the elements are arranged in columns: the TextBlock is explicitly placed in column 0 and the RadBusyIndicator spans across two columns. You should remove those redundant Grid.Column and Grid.ColumnSpan values.

    Don't use GridRowSpan unless your elements are arranged in columns or you want to create overlays (using z-index).

    <Grid x:Name="Grd_plan"
          Grid.Row="2">
      <Grid.RowDefinitions>
        <RowDefinition Height="auto" />   <!-- TextBlock row -->
        <RowDefinition Height="*"
                       MinHeight="50" />  <!-- DataGrid row -->
        <RowDefinition Height="*" />      <!-- RadBusyIndicator row -->
      </Grid.RowDefinitions>
    
      <TextBlock Grid.Row="0"
                 Text="planned..." />
    
      <DataGrid Grid.Row="1" ...>
    
      <telerik:RadBusyIndicator Grid.Row="2" 
                                HorizontalAlignment="Stretch" 
                                VerticalAlignment="Stretch" 
                                BusyContent="Loading pallets" 
                                IsBusy="{Binding IsLoadingGepandeMatrijsPalletten}" />
    </Grid>
    

    If you want to make the busy indicator to overlay the DataGrid, simply put them in the same row and set the Panel.ZIndex property to control their rendering order (z-index). There is no row span required (or reasonable).