Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Datagrid Performance

I am working with the WPF Toolkit data grid and it is scrolling extremely slow at the moment. The grid has 84 columns and 805 rows. (Including 3 fixed columns and the header is fixed.) Scrolling both horizontally and vertically is extremely slow. Virtualization is turned on and I have enabled column virtualization and row virtualization explicitly in the xaml. Is there anything to watch out for that can really effect performance, such as binding methods, or what xaml is in each celltemplate?

One thing to note is I am dynamically adding the columns on creation of the datagrid. Could that be effecting anything? (I also dynamically create the celltemplate at the same time so that my bindings are set right.)

Below is the code from the template for most of the cells that get generated. Basically for the columns I need to dynamically add (which is most of them), I loop through my list and add the columns using the AddColumn method, plus I dynamically build the template so that the binding statements properly index the right item in the collection for that column. The template isn't too complex, just two TextBlocks, but I do bind four different properties on each. It seems like I was able to squeeze out a little bit more performance by changes the bindings to OneWay:

 private void AddColumn(string s, int index)
    {
        DataGridTemplateColumn column = new DataGridTemplateColumn();
        column.Header = s;
        //Set template for inner cell's two rectangles
        column.CellTemplate = CreateFactViewModelTemplate(index);
        //Set Style for header, ie rotate 90 degrees
        column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
        column.Width = DataGridLength.Auto;
        dgMatrix.Columns.Add(column);
    }


    //this method builds the template for each column in order to properly bind the rectangles to their color
    private static DataTemplate CreateFactViewModelTemplate(int index)
    {
        string xamlTemplateFormat =
            @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
            xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
            <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay}"" />
            <TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay}"" />
            </Grid>
            </DataTemplate>";




        string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());

        return (DataTemplate)XamlReader.Parse(xamlTemplate);
    }
like image 586
ctrlalt313373 Avatar asked Mar 30 '09 15:03

ctrlalt313373


3 Answers

Since I can't see your source code it is quite hard to help you. Especially since the performance of a WPF application is influenced by a lot of things. For some hints on what to look out for see Optimizing WPF Application Performance. And yes - it greatly matters what xaml is used in each cell. Because usually performance problems do boil down to "too many elements". Did you know that a TextBox are I think 30 individual elements? I recommend you use the Performance Profiling Tools for WPF to find out more about your specific problem. Try to minimize the amount of elements you are using (e.g. by switching from TextBox to TextBlock where appropriate).

Also you have to check if the performance problems exist on any PC you try the application on. Maybe the PC you are using is forcing WPF into software based rendering. Or are you using any BitmapEffects?

Edit:
Looking at your code I would suggest you change

column.Width = DataGridLength.Auto;

to a reasonable fixed width, since the datagrid does not have to recalculate the width dynamically every time something changes (like adding rows, or even scrolling).

like image 67
Tobias Hertkorn Avatar answered Nov 07 '22 04:11

Tobias Hertkorn


A general tip for DataGrid performance issues: I had a problem with the DataGrid in which it took literally seconds to refresh after a window resize, column sort, etc. and locked up the window UI while it was doing so (1000 rows, 5 columns).

It came down to an issue (bug?) with the WPF sizing calculations. I had it in a grid with the RowDefinition Height="Auto" which was causing the rendering system to try and recalculate the size of the DataGrid at runtime by measuring the size of each and every column and row, presumably by filling the whole grid (as I understand it). It is supposed to handle this intelligently somehow but in this case it was not.

A quick check to see if this is a related problem is to set the Height and Width properties of the DataGrid to a fixed size for the duration of the test, and try running again. If your performance is restored, a permanent fix may be among these options:

  • Change the sizes of the containing elements to be relative (*) or fixed values
  • Set MaxHeight and MaxWidth of the DataGrid to a fixed value larger than it could get in normal use
  • Try another container type with different resizing strategy (Grid, DockPanel, etc)
like image 35
TripleAntigen Avatar answered Nov 07 '22 04:11

TripleAntigen


in one of my projects the following grid style setting was causing a major performance problem:

 <Style  TargetType='{x:Type controls:DataGrid}'>
    <Setter Property='ScrollViewer.CanContentScroll' Value='False' />
    ...

When I removed the ScrollViewer.CanContentScroll setting, the performance problem was gone.

like image 8
Hans van Dodewaard Avatar answered Nov 07 '22 06:11

Hans van Dodewaard