-1

I'm currently using a DataGrid. about 24 columns are created dynamically in C#.

There's always about 300 entries in my DataGrid (and since one entry represent a "title", I can't create paging systems, cause I have to get all the data in the same page).

It works well, but if I use DataGridTemplateColumns (because I need a styled column header which have a separator and 2 titles, as I need 2 sub columns on each column) and cell templates (still because I need these 2 sub columns), which has a double-binding (one binding for each sub column), when I load the Grid, it's just unusable...

I tried ALL types of virtualization (StackPanel, RowVirtualization, ColumnVirtualization with all different types of value combinations). The "best" performance I could get is with the RowVirtualization and ColumnVirtualization set to True.

It's now "usable", but still very slow when I do horizontal scrolling (even with a little graphic bug since I use a FrozenColumn...)

I even tried using my own ListView / GridView, and after working on it for hours (in order to reproduced the frozen column, etc...) There's still the same "issue".

It's not possible to use Data Virtualization (since there's "only" 24 columns with 285 rows, it will not user friendly at all).

Thanks !

EDIT 1 : Here is the code generating the columns

        ColumnCollection = new ObservableCollection<DataGridColumn>();
        DataGridTemplateColumn firstDtc_l = new DataGridTemplateColumn();
        firstDtc_l.Header = "Titles";
        FrameworkElementFactory spFactory_l = new FrameworkElementFactory(typeof(Grid));
        ColumnCollection.Add(firstDtc_l);
        int i = 0;

        foreach (string s in DynamicColumns)
        {
            DataGridTemplateColumn dtc_l = new DataGridTemplateColumn();
            Binding bindColor = new Binding();
            bindColor.Converter = new ChangedColorConverter();
            bindColor.ConverterParameter = "Column" + i;

            //DataTemplate
            DataTemplate dt_l = new DataTemplate("MyObject");
            spFactory_l = new FrameworkElementFactory(typeof(Grid));
            spFactory_l.Name = "CellTemplate";
            FrameworkElementFactory columnDefinition1 = new FrameworkElementFactory(typeof(ColumnDefinition));
            FrameworkElementFactory columnDefinition2 = new FrameworkElementFactory(typeof(ColumnDefinition));
            FrameworkElementFactory border1 = new FrameworkElementFactory(typeof(Border));
            border1.SetValue(Grid.ColumnProperty, 0);
            border1.SetValue(Border.BorderBrushProperty, Brushes.Gray);
            border1.SetValue(Border.BorderThicknessProperty, new Thickness(0,0,0,0));
            FrameworkElementFactory border2 = new FrameworkElementFactory(typeof(Border));
            border2.SetValue(Grid.ColumnProperty, 1);
            border2.SetValue(Border.BorderBrushProperty, Brushes.Gray);
            border2.SetValue(Border.BorderThicknessProperty, new Thickness(1, 0, 0, 0));
            FrameworkElementFactory textBlock1 = new FrameworkElementFactory(typeof(TextBlock));
            textBlock1.SetValue(Grid.ColumnProperty, 0);
            textBlock1.SetValue(TextBlock.ForegroundProperty, bindColor);
            Binding firstBind = new Binding("MyObject[Column"+i+"].FirstBinding");
            textBlock1.SetValue(TextBlock.TextProperty, localBind);
            FrameworkElementFactory textBlock2 = new FrameworkElementFactory(typeof(TextBlock));
            Binding secongBind = new Binding("MyObject[Column" + i + "].SecondBinding");
            textBlock2.SetValue(Grid.ColumnProperty, 0);
            textBlock2.SetValue(TextBlock.TextProperty, firstBind) 
            textBlock2.SetValue(TextBlock.ForegroundProperty, secongBind);
            border1.AppendChild(textBlock1);
            border2.AppendChild(textBlock2);

            spFactory_l.AppendChild(columnDefinition1);
            spFactory_l.AppendChild(columnDefinition2);
            spFactory_l.AppendChild(border1);
            spFactory_l.AppendChild(border2);
            dt_l.VisualTree = spFactory_l;

            dtc_l.Width = DataGridLength.Auto;
            dtc_l.CellTemplate = dt_l;
            dtc_l.Header = s;
            ColumnCollection.Add(dtc_l);
            i++;
        }   

The DataGrid is bound to a Collection of "TheObject". TheObject class has a public Dictionary<string, MyCell> MyObject { get; set; } MyCell class has FirstBinding and SecondBinding properties (string).

metalcam
  • 392
  • 2
  • 16
  • how is the performance without your DataGridTemplateColumn? maybe you should post the code for this. – blindmeis May 20 '11 at 07:59
  • I know that the low performance is because of the DataGridTemplaceColumns... but I can't use another type of column since I must have a Styled Header (not just a string as the header), and cell template (2 bindings for each cell) :/ – metalcam May 20 '11 at 08:07
  • can you post your code/xaml for the TemplateColumn? – blindmeis May 20 '11 at 08:13
  • I Edited my post. Notice that I use a DependencyProperty to load all the columns to the datagrid. In this method, I apply the HeaderStyle for each columns – metalcam May 20 '11 at 08:33
  • I have launched your example and the horizontal scrolling isn't so slow, it is much faster than vertical scrolling. But I don't know what the frozen column is, so I haven't reproduced this functionality and it might be the reason why my results are different. – vortexwolf May 20 '11 at 10:07
  • frozen column is really simple. Just set "FrozenColumnCount" to "1" :) In your reproduced datagrid, have you 20+ DataGridTemplateColumns with the same binding structure (I mean the datagrid bound to a collection of objects which have a Dictionary of objects wich have 2 strings, where cell templates are bound to ?) – metalcam May 20 '11 at 10:16
  • The problem is that the WPF App is a class library hosted by an Excel add-in. So... impossible to load the DLL correctly :/ But last time, I figured out that the performance were far better when the DLL was nos hosted. Since for now my environment is Excel 2003 with windows XP, I'm pretty sure it will be more efficient on Windows 7 / Excel 2010 ! I'll have to try this one... – metalcam May 20 '11 at 13:47

1 Answers1

-1

I had a similar 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)
TripleAntigen
  • 2,221
  • 1
  • 31
  • 44