none
WPF Datagrid - Add a "Super header" to a datagrid with a horizontal scroll RRS feed

  • Question

  • Hi,

    A WPF datagrid control with "Super Headers":

    SuperHeaderA                   SuperHeaderB                  SuperHeaderC

    SubHeaderA SubHeaderB   SubHeaderC SubHeaderD  SubHeaderE SubHeaderF SubHeaderG SubHeaderH

    <------------------------------------Scrollbar----------------------------------->

    When the datagrid goes "off-page", the scrollbar will scroll across the SubHeaders, however the SuperHeaders would stay in-place/static and not scroll with the SubHeaders.

    Is there any way to "bind" the SuperHeader to the position of the SubHeaders, whereby the SuperHeaders would shrink/grow, or scroll with the SubHeaders based on the movement of the scrollbar? Attempted to place the scrollbar on the parent control, though the grid renders all of the data before displaying the data and takes 2+ minutes to display larger datasets (2000+ records) instead of a few seconds with the same large recordset.

    Please find example below:

    <Grid>
    ...
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="10" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderA, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderB, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderC, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderD, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderE, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderF, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderG, Path=ActualWidth}" />
                            <ColumnDefinition Width="{Binding ElementName=SubHeaderH, Path=ActualWidth}" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>

                        <Border Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="4">
                            <Label Content="SuperHeaderA" />
                        </Border>

                        <Border Grid.Row="0" Grid.Column="5" Grid.ColumnSpan="4" >
                            <Label Content="SuperHeaderB" />
                        </Border>

                        <Border Grid.Row="0" Grid.Column="9" Grid.ColumnSpan="2" >
                            <Label Content="SuperHeaderC" />
                        </Border>

                    <DataGrid
                            RowHeaderWidth="10"
                            AlternationCount="2"
                            AutoGenerateColumns="False"
                            Background="Transparent"
                            BorderThickness="0"
                            CanUserAddRows="True"
                            CanUserDeleteRows="True"
                            DockPanel.Dock="Left"
                            FrozenColumnCount="1"
                            Grid.Column="0"
                            Grid.ColumnSpan="20"
                            Grid.Row="1"
                            IsSynchronizedWithCurrentItem="True"
                            ItemContainerStyle="{StaticResource StyleDataGridAlternating}"
                            ItemsSource="{Binding EntityCensus, Mode=TwoWay, NotifyOnSourceUpdated=True}"
                            Name="DgEntityCensus"
                            SelectedItem="{Binding SelectedEntity, Converter={StaticResource DataGridNewItem}}"
                            SelectionMode="Single"
                            Style="{DynamicResource DataGridStyle}"
                            EnableColumnVirtualization="True"
                            EnableRowVirtualization="True"
                            HorizontalAlignment="Left"
                            HorizontalScrollBarVisibility="Visible"
                            VerticalScrollBarVisibility="Visible"
                            Width="{Binding ElementName=AView, Path=ActualWidth}"
                            Margin="0,0,-10,0">

     <DataGrid.Columns>
     ...
     </DataGrid.Columns>
    ...
    </Grid>

    Please advise!

    Thanks!

    -O



    • Edited by Option Wednesday, June 4, 2014 9:10 PM
    Wednesday, June 4, 2014 9:00 PM

Answers

  • Hi,

    To be honest, I didn’t understand this issue. Let’s clarify this issue first.

    >>Is there any way to "bind" the SuperHeader to the position of the SubHeaders…based on the movement of the scrollbar? <<

    Based on my understanding, if we move the specify SuperHeader, The column of the DataGrid will move to the position where the specify SuperHeader located. Let’s see the screenshot below,

    1. If this is your purpose regarding move the position. I am afraid that we cannot achieve this goal.

    2. I reviewed the code. In my view, we cannot bind the Actual Width. Since the Actual Width is always 0 or null before rendering.

    3. If you want to scroll SuperHeader and the DataGrid together. We can achieve this goal. Get the first scrollbar position. And then set to the second scrollbar position.

    <ScrollViewer Name="sv1" Height="100" HorizontalScrollBarVisibility="Auto" ScrollChanged="ScrollChanged">
        <Grid Height="1000" Width="1000" Background="Green" />
    </ScrollViewer>
    <ScrollViewer Name="sv2" Height="100" HorizontalScrollBarVisibility="Auto" ScrollChanged="ScrollChanged">
        <Grid Height="1000" Width="1000" Background="Blue" />
    </ScrollViewer>
    
    
    private void ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (sender == sv1)
        {
            sv2.ScrollToVerticalOffset(e.VerticalOffset);
            sv2.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
        else
        {
            sv1.ScrollToVerticalOffset(e.VerticalOffset);
            sv1.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
    }

    If I misunderstood or my points are incorrect, please let me know.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Yang,Chenfei Thursday, June 12, 2014 6:53 AM
    Thursday, June 5, 2014 11:46 AM

All replies

  • Hi,

    To be honest, I didn’t understand this issue. Let’s clarify this issue first.

    >>Is there any way to "bind" the SuperHeader to the position of the SubHeaders…based on the movement of the scrollbar? <<

    Based on my understanding, if we move the specify SuperHeader, The column of the DataGrid will move to the position where the specify SuperHeader located. Let’s see the screenshot below,

    1. If this is your purpose regarding move the position. I am afraid that we cannot achieve this goal.

    2. I reviewed the code. In my view, we cannot bind the Actual Width. Since the Actual Width is always 0 or null before rendering.

    3. If you want to scroll SuperHeader and the DataGrid together. We can achieve this goal. Get the first scrollbar position. And then set to the second scrollbar position.

    <ScrollViewer Name="sv1" Height="100" HorizontalScrollBarVisibility="Auto" ScrollChanged="ScrollChanged">
        <Grid Height="1000" Width="1000" Background="Green" />
    </ScrollViewer>
    <ScrollViewer Name="sv2" Height="100" HorizontalScrollBarVisibility="Auto" ScrollChanged="ScrollChanged">
        <Grid Height="1000" Width="1000" Background="Blue" />
    </ScrollViewer>
    
    
    private void ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (sender == sv1)
        {
            sv2.ScrollToVerticalOffset(e.VerticalOffset);
            sv2.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
        else
        {
            sv1.ScrollToVerticalOffset(e.VerticalOffset);
            sv1.ScrollToHorizontalOffset(e.HorizontalOffset);
        }
    }

    If I misunderstood or my points are incorrect, please let me know.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Yang,Chenfei Thursday, June 12, 2014 6:53 AM
    Thursday, June 5, 2014 11:46 AM
  • Hi,

    Since we haven't heard from you for a long time, I temporarily close this case. I mark useful reply as answer. If you have any concerns, please free feel to reopen it or submit a new question.

    Thanks for your understanding.

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, June 12, 2014 6:53 AM