ScrollViewer slow performance with DataGrid

2019-02-21 17:41发布

问题:

I have the following scenario:

<ScrollViewer>
    <Grid>
         <!--many other controls-->
         <DataGrid />
    </Grid>
</ScrollViewer>

Now, when I bind DataGrid to large amount of data (around 10.000 rows) I am having very slow perfomance. In fact, i get OutOfmemory exception (and I have 8 GB memory)! I read somewhere that this is because ScrollViewer overrides DataGrid virtualisation (or something like that), but I don't know how to prevent that. If I remove the ScrollViewer, problem solved! The data loads in less than a second.

I want to keep the ScrollViewer (because of other controls) and have good performance. Is that possible? If not, is there any other solution-workaround?

回答1:

A common workaround to these sorts of problems is to add an invisible "sizing element" in the same Row as the DataGrid, then you can bind DataGrid.Height to the ActualHeight of the sizing element. This way, your DataGrid will always consume the Height of the RowDefinition. Example

<ScrollViewer>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Button Content="Some Control.." />
        <Rectangle Name="sizingElement"
                   Grid.Row="1"
                   Fill="Transparent"
                   Margin="1"/>
        <DataGrid Grid.Row="1"
                  Height="{Binding ElementName=sizingElement,
                                   Path=ActualHeight, FallbackValue=1}">
            <!--...-->
        </DataGrid>
        <Button Content="Some more controls etc.." Grid.Row="2"/>
    </Grid>
</ScrollViewer>


回答2:

The outer ScrollViewer effectively gives the DataGrid as much space as it likes, that way its height becomes huge, showing all rows at once. Just restrict the DataGrid by expclicitly setting a height on it for example.