How do I include a custom row at the end of a DataGrid in Silverlight?
Asked Answered
D

3

10

I have a DataGrid in my Silverlight application and it works nicely, adding a row or removing a row as I manipulate the ItemsSource collection. However, I want there to be an additional row, or control that always appears after the last data row.

I can get the additional control to appear after the last row using a ControlTemplate and setting the RowsPresenter row to Auto height, but this means the rows never scroll when the render area gets too small. However, if I change the RowsPresenter row height to Star, the rows scroll but the additional control appears pinned to the bottom of the data grid rather than to the bottom of the last row.

Is there a way I can have the Star height behavior on the RowsPresenter while still having my control appear the way I want?

My current thinking is that I need to somehow use the LoadingRow event to find the position of the last row and use a Canvas or similar to place my control in the appropriate location.

Thoughts?

Thanks in advance for the help.

Update

I also asked a question (and ultimately answered) about pinning one control below another, which could be used to fix this issue if you don't want the custom row to scroll with the rest of the rows (such as in my case, where I wanted another datagrid header row to show totals and float over the other rows).

How do I pin one control below another in Silverlight?

Delphiadelphic answered 4/2, 2009 at 18:25 Comment(0)
D
6

I solved my problem last night in a flurry of inspiration. I notice that no one else has voted for this question so this answer may not be helpful to anyone, but just in case.

First of all, I combined my custom row control and RowsPresenter in a grid of two rows, each row sized to Auto. I then placed the grid inside a ScrollViewer and then sized the scroll viewer row to Star sizing. I did not add the VerticalScrollbar template part into my template as this only scrolls the RowsPresenter.

This gave me the exact behaviour I was looking for where a row is added and the custom row remains pinned to the bottom of the last data row. When the rows and custom row overflow off the end of the visible area, the scrollbar appears to allow scrolling while keeping the headers fixed in place.

Job done. I hope someone finds this helpful. Below is my ControlTemplate XAML.

<ControlTemplate TargetType="swcd:DataGrid" x:Key="DataGridTemplate">
    <Border
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}">

        <Grid Name="Root" Background="{TemplateBinding Background}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <swcdp:DataGridColumnHeader Name="TopLeftCornerHeader" Grid.Column="0"/>
            <swcdp:DataGridColumnHeadersPresenter Name="ColumnHeadersPresenter" Grid.Column="1"/>
            <swcdp:DataGridColumnHeader Name="TopRightCornerHeader" Grid.Column="2"/>

            <ScrollViewer
                Grid.Row="1"
                Grid.Column="1"
                Grid.ColumnSpan="1"
                Padding="0,0,0,0"
                BorderThickness="0,0,0,0"
                VerticalScrollBarVisibility="Auto">
                <Grid >
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>

                    <swcdp:DataGridRowsPresenter Name="RowsPresenter" Grid.Row="0" />

                    <Border
                        Margin="1,1,1,1"
                        Padding="2,2,2,2"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        Grid.Row="1">
                        <Grid Background="{TemplateBinding Background}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>

                            <TextBlock
                                Grid.Row="0"
                                TextAlignment="Left"
                                TextWrapping="NoWrap"
                                Text="Add a new item using the lists below:" />

                            <mystuff:MySelectionControl
                                HorizontalContentAlignment="Stretch"
                                Grid.Row="1"
                                SelectionChanged="OnSelectionChanged"/>
                        </Grid>
                    </Border>
                </Grid>
            </ScrollViewer>

            <Rectangle Name="BottomLeftCorner" Grid.Row="3" Grid.ColumnSpan="2" />
            <Grid Grid.Column="1" Grid.Row="3">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Rectangle Name="FrozenColumnScrollBarSpacer" />
                <ScrollBar Name="HorizontalScrollbar" Grid.Column="1" Orientation="Horizontal" Height="18" />
            </Grid>
            <Rectangle Name="BottomRightCorner" Grid.Column="2" Grid.Row="3" />
        </Grid>
    </Border>
</ControlTemplate>
Delphiadelphic answered 5/2, 2009 at 15:11 Comment(1)
+1 Could you write an example of use of your template? Thanks!Komsomolsk
I
2

Not sure if this helps for Silverlight, but I added a totals row to a WPF DataGrid by adding and invisible column, called IsTotal. I was able to get this row to always appear at the buttom of the grid using custom grouping / sorting. The grouping / sort order was configured to use this column as the primary sort, with a fix direction. Seems to work well.

Infrequency answered 21/10, 2009 at 8:50 Comment(1)
That's a cool solution for a row of data. I like it. It didn't suit what I needed but it's still an interesting approach. Thanks.Delphiadelphic
I
2

First, create a Grid for the DataGrid and the pinned control:

<Grid Grid.Row="0" VerticalAlignment="Top">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />               
        <RowDefinition Height="Auto" />            
    </Grid.RowDefinitions>

    <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />

    <TextBlock Grid.Row="1" Text="Hello World" /> <!-- The pinned control. -->
</Grid>

The trick is VerticalAlignment="Top" - when the DataGrid is smaller than the available height, it will move to the top of the available space and the pinned control will appear under it.

Then, put this Grid into a container that stretches vertically, for example in a row of another Grid with Star height:

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <!-- RowDefition for the Grid with the DataGrid with the pinned control. --> 
        <!-- If you want to have some other controls, -->
        <!-- add other RowDefinitions and put these controls there.  -->
        <RowDefinition Height="*" /> 
    </Grid.RowDefinitions>

    <!-- The internal Grid for the DataGrid & the pinned control. -->
    <Grid Grid.Row="0" VerticalAlignment="Top">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />               
            <RowDefinition Height="Auto" />            
        </Grid.RowDefinitions>

        <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />

        <TextBlock Grid.Row="1" Text="Hello World" /> <!-- The pinned control. -->
    </Grid>
</Grid>

Instead of the root Grid you may have any other container that stretches vertically, the important thing is that it tries to fill all the available space for it.

Idea answered 14/12, 2013 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.