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 DataGridTemplateColumn
s (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).