locked
DataGrid height in WPF Grid Row with star height RRS feed

  • Question

  • I have searched the net like crazy to try and find a solution to this issue, but nothing I have tried works.

    Here's my XAML (I am using the MVVM Light framework):

    <UserControl x:Class="UI.View.DataAcquisitionView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:res="clr-namespace:UI.Properties"
                 mc:Ignorable="d" 
                 d:DesignHeight="300"
                 d:DesignWidth="300"
                 DataContext="{Binding Source={StaticResource Locator}, Path=DataAcquisition}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
    
            <TextBlock Name="labelInstructions"
                       Text="{x:Static res:Resources.LabelInstructions_Content}"
                       TextWrapping="WrapWithOverflow"
                       Width="Auto"
                       Height="Auto" />
    
            <Button Name="buttonStart"
                    Content="{x:Static res:Resources.ButtonStart_Content}"
                    Grid.Row="1"
                    Margin="5"
                    Width="80"
                    Height="25"
                    Command="{Binding AcquireDataCommand}" />
    
            <TextBlock Name="labelStatus"
                       Grid.Row="2"
                       TextWrapping="WrapWithOverflow"
                       HorizontalAlignment="Center"
                       Text="{Binding Path=DataAcquisitionProgressText, Mode=OneWay}" />
    
            <DataGrid Name="dataGridAcquiredData"
                      Grid.Row="3"
                      AutoGenerateColumns="False"
                      ItemsSource="{Binding Path=AcquiredData, Mode=OneWay}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="{x:Static res:Resources.DataGrid_Column1_Header}"
                                        Binding="{Binding Path=DataColumn1}" />
                    <DataGridTextColumn Header="{x:Static res:Resources.DataGrid_Column2_Header}"
                                        Binding="{Binding Path=DataColumn2}" />
                    <DataGridTextColumn Header="{x:Static res:Resources.DataGrid_Column3_Header}"
                                        Binding="{Binding Path=DataColumn3}" />
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </UserControl>

    As you can see, the DataGrid is being placed in a Grid Row with a Height of '*' to use all remaining height. So, the expectation is that the DataGrid should size itself to fit that Row. I have read many places that state that the DataGrid should work as expected when placed in a Grid Row with starred height.

    However, when filled with data, the DataGrid expands beyond the limits of the Row, without showing scrollbars. Shouldn't it use the ActualHeight of the Grid Row and adjust it's Height to that?

    If I set the Row Height to be a fixed size, say 200px, it works as expected. But, I want the DataGrid to take up the entire lower portion of the UserControl.

    This seems so simple, but yet has been extremely frustrating! I have created many other WPF forms, and all of the other controls that I have used work as expected. It just seems to be the DataGrid control.

    Thanks for any help you can provide,

    Todd

    Edit: If it helps at all, this UserControl is being placed into a Grid Row on a main Window that is also using a Height of '*'. I can always paste some of the XAML for that too.

    • Edited by jeepfan Wednesday, June 12, 2013 3:18 PM Clarification
    Wednesday, June 12, 2013 2:51 PM

Answers

  • Hi again, i remember i ran into this problem with the HeaderedContentControl once. It's something to do with the control's template. I created a style that overrides the template and it worked.

        <Style TargetType="HeaderedContentControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type HeaderedContentControl}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
    
                            <ContentPresenter ContentSource="Header" />
    
                            <ContentPresenter ContentSource="Content" Grid.Row="1"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    Hope this helps!

    • Marked as answer by jeepfan Thursday, June 13, 2013 3:21 PM
    Thursday, June 13, 2013 2:13 PM

All replies

  • maybe you put this UserControl inside a ScrollViewer? It's the only explanation i can think of. 
    Wednesday, June 12, 2013 3:21 PM
  • Its look like a strange issue, I suggest you post complete code or else try to reproduce same issue in a sample application, if you are not able to reproduce then its problem with your some other control.

    if you are able to reproduce post the code here.

    lets try something like, add stackpanel in last row in place of datagrid and add datagrid as children to this stackpanel, make sure that both stackpanel and datagrid should not have any height.

    lets hope this will help you.


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    Wednesday, June 12, 2013 3:46 PM
  • Thank you for your reply.

    I created a demo application, which worked as expected. So, it has something to do with how I am implementing it. I am basically creating a Wizard-like application, and so the UserControls are nested 3 deep (MainWindow contains WizardUserControl contains PageUserControls). Anyway, I am going to continue to investigate the demo application (turning it into a Wizard-like interface), and see if I can get the error to occur. I will make sure to post my findings.

    Todd

    Wednesday, June 12, 2013 8:38 PM
  • Hi Todd,

    The code snippet you posted looks fine. The Grid will limit the size the DataGrid. If you cannot see the ScrollBar show up, it is very likely the Grid itself have a larger Height than you thought.

    As agugglez mentioned above, please check the ancestors of this UserControl for StackPanel or Auto sizing Grid row. These are the most likely cause of the issue.

    Best regards,


    Min Zhu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, June 13, 2013 1:33 AM
  • I've finally narrowed it down to a problem with the HeaderedContentControl. If I simply place the DataGrid in a layout Grid, it works fine. If I place it into a HeaderedContentControl, it acts like the HeaderedContentControl is unlimited size. By default, the HeaderedContentControl has a Width and Height of Auto. But, even if I set the Width and Height to fixed values (say 200px by 200px), the DataGrid still doesn't work as expected. Kind-of interesting.

    Demo XAML:

    <Window x:Class="WpfDataGridTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow"
            Height="350"
            Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
    
            <Button Name="buttonStart"
                    Content="Start"
                    Margin="5"
                    Width="80"
                    Height="25"
                    Click="ButtonStart_Click" />
    
            <HeaderedContentControl Grid.Row="1">
                <DataGrid Name="dataGridAcquiredData"
                          AutoGenerateColumns="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Datapoint"
                                            Binding="{Binding Path=.}" />
                    </DataGrid.Columns>
                </DataGrid>
            </HeaderedContentControl>
            
            <DataGrid Name="dataGridAcquiredData2"
                      Grid.Row="2"
                      AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Datapoint"
                                        Binding="{Binding Path=.}" />
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>
    

    Demo code behind:

    namespace WpfDataGridTest
    {
        public partial class MainWindow
        {
            private readonly AcquiredData dataAcquisition;
    
            public MainWindow()
            {
                InitializeComponent();
    
                this.dataAcquisition = new AcquiredData();
            }
    
            private void ButtonStart_Click(object sender, System.Windows.RoutedEventArgs e)
            {
                this.dataAcquisition.FillAcquiredData();
    
                this.dataGridAcquiredData.ItemsSource = this.dataAcquisition.Data;
                this.dataGridAcquiredData2.ItemsSource = this.dataAcquisition.Data;
            }
        }
    }
    

    Demo AcquiredData class:

    namespace WpfDataGridTest
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.ComponentModel;
    
        public class AcquiredData : INotifyPropertyChanged
        {
            private ObservableCollection<double> data;
     
            public event PropertyChangedEventHandler PropertyChanged;
    
            public IEnumerable<double> Data
            {
                get
                {
                    return this.data;
                }
            }
    
            public void FillAcquiredData()
            {
                this.data = new ObservableCollection<double>();
    
                for (var i = 0; i <= 1000; i++)
                {
                    this.data.Add(Math.Sin(i));
                }
                
                this.RaisePropertyChangedEvent("Data");
            }
    
            private void RaisePropertyChangedEvent(string propertyName)
            {
                var handler = this.PropertyChanged;
    
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
    

    Anyway, unless I am missing something, it is looking like I can't use the HeaderedContentControl.

    Thanks for all of the help. Your replies pointed me in the right direction.

    Todd

    Thursday, June 13, 2013 1:31 PM
  • Hi again, i remember i ran into this problem with the HeaderedContentControl once. It's something to do with the control's template. I created a style that overrides the template and it worked.

        <Style TargetType="HeaderedContentControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type HeaderedContentControl}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
    
                            <ContentPresenter ContentSource="Header" />
    
                            <ContentPresenter ContentSource="Content" Grid.Row="1"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    Hope this helps!

    • Marked as answer by jeepfan Thursday, June 13, 2013 3:21 PM
    Thursday, June 13, 2013 2:13 PM
  • That did it! Thank you very much agugglez!
    Thursday, June 13, 2013 3:21 PM