0

I'm building a resolution-independent WPF application. The MainWindow uses a ContentControl to load views dynamically:

<Border Grid.Row="1" Grid.Column="1" BorderThickness="15,15,0,15" BorderBrush="{StaticResource GradientRARedOrange}">
<ScrollViewer    
  VerticalScrollBarVisibility="Auto"
  HorizontalScrollBarVisibility="Auto">
    <ContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{Binding CurrentView}" />
</ScrollViewer>
</Border>

In one of these views, I have two DataGrids arranged in a Grid. They initially display correctly, but once data is loaded, both DataGrids expand vertically to fit all rows. As a result, the UserControl (view) grows, and the outer container (likely a ScrollViewer in a parent) shows a scrollbar, instead of the DataGrid itself showing internal scrollbars.

My expectation is: the DataGrid should stay within its allocated space (defined by Grid.Row with Height="*"), and show a scrollbar internally when content overflows.

The View:

 <Grid Background="{StaticResource ColorMyColor2}" ClipToBounds="True">
 <Grid.RowDefinitions>
     <RowDefinition Height="15*"/>            
     <RowDefinition Height="70*"/>            
     <RowDefinition Height="15*"/>            
 </Grid.RowDefinitions>

 <Grid.ColumnDefinitions>
     <ColumnDefinition Width="20*"/>
     <ColumnDefinition Width="65*"/>
     <ColumnDefinition Width="15*"/>
 </Grid.ColumnDefinitions>   

 <Grid Grid.Row="1" Grid.Column="0" Margin="20">
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <DataGrid x:Name="" 
                 Grid.Row="0"
                 HorizontalAlignment="Stretch"  
                 VerticalAlignment="Stretch"
                 AutoGenerateColumns="False" 
                 ScrollViewer.VerticalScrollBarVisibility="Auto"                        
                 ScrollViewer.HorizontalScrollBarVisibility="Auto"
                 SelectedItem="{Binding , Mode=TwoWay}"
                 ItemsSource="{Binding }" 
                 Style="{StaticResource DataGridTheme1}">
         <DataGrid.Columns>
             <DataGridTextColumn Header="" Binding="{Binding }"  />
         </DataGrid.Columns>
     </DataGrid>
 </Grid>


 <Grid Grid.Row="1" Grid.Column="1" Margin="20">
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
     </Grid.RowDefinitions>
     <DataGrid x:Name="" 
                 Grid.Row="0"
                 HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch"
                 IsReadOnly="True"
                 SelectionMode="Single"
                 SelectionUnit="FullRow"
                 AutoGenerateColumns="False" 
                 ScrollViewer.VerticalScrollBarVisibility="Auto"                        
                 ScrollViewer.HorizontalScrollBarVisibility="Auto"
                 ItemsSource="{Binding Items}"
                 Style="{StaticResource DataGridTheme1}">
         <DataGrid.Columns>
             <DataGridTextColumn Header=""  Binding="{Binding }" />
             <DataGridTextColumn Header=""  Binding="{Binding }" />
         </DataGrid.Columns>
     </DataGrid>
 </Grid>    
     
 </Grid>

Style:

     <Style TargetType="{x:Type DataGrid}"
  x:Key="DataGridTheme1">
 <Setter Property="Background" Value="{StaticResource ColorMyColor3}"/>
 <Setter Property="Foreground" Value="{StaticResource ColorMyColor1}"/>
 <Setter Property="RowBackground" Value="Transparent"/>
 <Setter Property="AlternatingRowBackground" Value="{StaticResource ColorMyColor2}"/>
 <Setter Property="GridLinesVisibility" Value="None"/>
 <Setter Property="BorderThickness" Value="0"/>
 <Setter Property="CanUserAddRows" Value="False"/>
 <Setter Property="AutoGenerateColumns" Value="False"/>
 <Setter Property="HeadersVisibility" Value="Column"/>
 <Setter Property="RowHeaderWidth" Value="0"/>
 <Setter Property="FontSize" Value="{StaticResource FontSizeMedium}"/>
 <Setter Property="FontFamily" Value="{StaticResource FontPrimary}"/>
 <Setter Property="Padding" Value="4"/>
 <Setter Property="SelectionMode" Value="Single"/>
 <Setter Property="SelectionUnit" Value="FullRow"/>
 <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
 <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
 <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
 <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
       <Style TargetType="DataGridRow">
   <Setter Property="Background" Value="Transparent"/>
   <Setter Property="MinHeight" Value="28"/>
   <Setter Property="SnapsToDevicePixels" Value="True"/>
   <Setter Property="HorizontalAlignment" Value="Stretch"/>
   <Setter Property="VerticalAlignment" Value="Center"/>
   <Setter Property="FontSize" Value="{StaticResource FontSizeMedium}"/>
   <Setter Property="FontFamily" Value="{StaticResource FontPrimary}"/>
   <Setter Property="BorderThickness" Value="0"/>
   <Setter Property="Effect">
       <Setter.Value>
           <DropShadowEffect BlurRadius="0" Opacity="0"/>
       </Setter.Value>
   </Setter>
   <Style.Triggers>
       <Trigger Property="IsMouseOver" Value="True">
           <Setter Property="Background" Value="#EEE"/>
       </Trigger>
       <Trigger Property="IsSelected" Value="True">
           <Setter Property="Background" Value="#FFDDDDDD"/>
       </Trigger>
   </Style.Triggers>
     <Style TargetType="DataGridCell">
 <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
 <Setter Property="Template">
     <Setter.Value>
         <ControlTemplate TargetType="DataGridCell">
             <Border x:Name="border"
               Background="{TemplateBinding Background}"
               BorderBrush="{TemplateBinding BorderBrush}"
               BorderThickness="{TemplateBinding BorderThickness}">
                 <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left" Margin="4,0,4,0"/>
             </Border>
             <ControlTemplate.Triggers>
                 <Trigger Property="IsSelected" Value="True">
                     <Setter TargetName="border" Property="Background" Value="{StaticResource GradientRAOrangeRed}"/>
                     <Setter TargetName="border" Property="BorderBrush" Value="{StaticResource GradientRAOrangeRed}"/>
                 </Trigger>
             </ControlTemplate.Triggers>
         </ControlTemplate>
     </Setter.Value>
 </Setter>

How can I force the DataGrid to stay within the height defined by its Grid.Row, and have the scrollbar appear inside the DataGrid, not in the parent container?

I don't want to use MaxHeight as the user should be able to resize the App as he wants.

I feel like I'm overlooking a simple but critical layout constraint.

4
  • Why are you wrapping your ContentControl with a ScrollViewer ? Are you not wanting to be dependent on the DataGrid ScrollViewer ? Commented Jun 16 at 12:51
  • Well, the idea behind wrapping the ContentControl in a ScrollViewer was to provide a fallback: in case I made a mistake in layout handling or didn't properly account for resolution/dimension changes, I wanted the user to still be able to scroll through the View. However, it turned out that this was exactly the reason why the DataGrids didn’t respect their row definitions. That said, I’d still appreciate if there were a reliable way to force a DataGrid to obey its row height, even when it's inside a scrollable container Commented Jun 16 at 13:19
  • The ContentControl has both Horizontai and Vertical Aligment set to "Stretch". The Border has the Grid.Row and Grid.Column Attached properties set. What is the definition of the Grid that the Border is a child of ? Is the project available for review ? Commented Jun 16 at 14:32
  • This is the Parent Grid of the Border / ContentControl <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> Commented Jun 17 at 8:20

1 Answer 1

0

Do the following to fill the client area of a window with two DataGrids side b y side.

There is a control which inherits directly from DataGrid and is named DataGridView.xaml. The window that hosts DataGridView.xaml is MainWindow.xaml which is also the StartupUri in App.xaml.

DataGridView.xaml

<DataGrid 
    x:Class="Application.DataGridView"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    AutoGenerateColumns="False" Margin="5"
    RowHeaderWidth="0" RowHeight="30"
    HorizontalScrollBarVisibility="Hidden"
    VerticalScrollBarVisibility="Visible">

    <DataGrid.Columns>
        <DataGridTextColumn
            Width="Auto"
            Binding="{Binding Description}"
            Header="Description"/>
        <DataGridTextColumn
            Width="*"
            Binding="{Binding Comments}"
            Header="Comments"/>
        <DataGridTextColumn
            Width="Auto"
            Binding="{Binding Date}"
            Header="Date"
            IsReadOnly="True" />
    </DataGrid.Columns>
            
</DataGrid>

DataGridView.xaml.cs

namespace Application;

public partial class DataGridView : System.Windows.Controls.DataGrid
{
    public DataGridView() => InitializeComponent();        
}

MainWindow.xaml

<Window 
    x:Class="Application.MainWindow"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    xmlns:l="clr-namespace:Application"
    
    WindowStartupLocation="CenterScreen"
    Title="DataGrid EXample"        
    Height="450" Width="800">

    <Grid Margin="10">
        
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        
        <l:DataGridView Grid.Column="0"/>
        <l:DataGridView Grid.Column="1"/>
        
    </Grid>
  
</Window>

MainWindow.xaml.cs

namespace Application;

public partial class MainWindow : System.Windows.Window
{
    public MainWindow() => InitializeComponent();
}

And finally, App.xaml

<Application    
    x:Class="Application.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"             
    StartupUri="MainWindow.xaml">
</Application>

The result

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.