Problem with GridColumnWidthKeeper when rows get loaded and unloaded solved
Problem with GanttRow being null in certain row loading situations solved
Author Archives: hasse
Speed of WPF Gantt
It is easy to make the WPF Gantt slow, just bog it down with lots of time items that has lots of details (complex internal markup).
This article is about how to make the WPF Gantt really fast.
There are two important things to optimize:
1. The Gantt rows
2. The Time Items
The Gantt rows
The Gantt rows can be optimized by limiting their rendering to only show the ones on screen. This is handled by standard WPF Virtualization implemented by VirtualizingStackPanel.
Example:
If you have your Gantt Rows in a Items control (if it is a tree view then it is really one items control per node):
<ItemsControl x:Name="_ItemsControl" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard" ScrollViewer.CanContentScroll="True" ItemTemplate="{StaticResource _GanttRowTemplate}" ItemsSource="{Binding Path=Resources}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.Template> <ControlTemplate> <Border HorizontalAlignment="Stretch" BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}"> <ScrollViewer x:Name="_ScrollViewer" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsDeferredScrollingEnabled="True" CanContentScroll="True" Padding="{TemplateBinding Control.Padding}" ScrollChanged="ScrollViewer_ScrollChanged" Focusable="False"> <ItemsPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> </ScrollViewer> </Border> </ControlTemplate> </ItemsControl.Template> </ItemsControl>
Doing this will stop WPF from wasting time on stuff that is not currently on screen. And WPF will create the GanttRows when scrolled into view.
The TimeItems
The Time items are not in a StackPanel so we need to use a different technique. We need a way to decide if a should be on screen or not.
We do this by implementing the event OnVirtualizeTimeItemCheck. In this event we get information about the bound object – that YOU know how to interpret – and the ability to say if it should be visible or not. We inform the Gantt that it should not be visible by setting e.SuggestedVisibility to Collapsed.
void _GanttControl_OnVirtualizeTimeItemCheck(object sender, OnVirtualizeTimeItemCheckArgs e) { if (e.TimeItemObject is WpfApplication10.Task) { var t=e.TimeItemObject as WpfApplication10.Task; if (t.Begin < e.VisibleAreaStop && t.End > e.VisibleAreaStart) e.SuggestedVisibility = System.Windows.Visibility.Visible; else e.SuggestedVisibility = System.Windows.Visibility.Collapsed; } }
The easiest way to decide if it should be on screen is like above: If the start is smaller than stop of view AND the stop is bigger than start of view. This covers the cases when time items are partly on screen, and when time items span the whole screen and beyond.
Summary
If you have large datasets like 1000 rows and 1000 time items per row – you really have to follow these guidelines. But you see good effects long before that.
Below 1 million Time items – Gantt still renders fast.
GTP.NET.SL 2.12.13
Added DateScaler WeekSpanFirstFormat and WeekSpanSecondFormat to allow for better control of WeekSpan presentation
New wpf performance sample added
Many improvements for performance
Added loaded animation
OnVirtualizeTimeItemCheck event
issues with userdraw not always getting measured correctly fixed.
Speed of WPF Gantt
It is easy to make the WPF Gantt slow, just bog it down with lots of time items that has lots of details (complex internal markup).
This article is about how to make the WPF Gantt really fast.
There are two important things to optimize:
1. The Gantt rows
2. The Time Items
The Gantt rows
The Gantt rows can be optimized by limiting their rendering to only show the ones on screen. This is handled by standard WPF Virtualization implemented by VirtualizingStackPanel.
Example:
If you have your Gantt Rows in a Items control (if it is a tree view then it is really one items control per node):
<ItemsControl x:Name="_ItemsControl" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard" ScrollViewer.CanContentScroll="True" ItemTemplate="{StaticResource _GanttRowTemplate}" ItemsSource="{Binding Path=Resources}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.Template> <ControlTemplate> <Border HorizontalAlignment="Stretch" BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}"> <ScrollViewer x:Name="_ScrollViewer" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsDeferredScrollingEnabled="True" CanContentScroll="True" Padding="{TemplateBinding Control.Padding}" ScrollChanged="ScrollViewer_ScrollChanged" Focusable="False"> <ItemsPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> </ScrollViewer> </Border> </ControlTemplate> </ItemsControl.Template> </ItemsControl>
Doing this will stop WPF from wasting time on stuff that is not currently on screen. And WPF will create the GanttRows when scrolled into view.
The TimeItems
The Time items are not in a StackPanel so we need to use a different technique. We need a way to decide if a should be on screen or not.
We do this by implementing the event OnVirtualizeTimeItemCheck. In this event we get information about the bound object – that YOU know how to interpret – and the ability to say if it should be visible or not. We inform the Gantt that it should not be visible by setting e.SuggestedVisibility to Collapsed.
void _GanttControl_OnVirtualizeTimeItemCheck(object sender, OnVirtualizeTimeItemCheckArgs e) { if (e.TimeItemObject is WpfApplication10.Task) { var t=e.TimeItemObject as WpfApplication10.Task; if (t.Begin < e.VisibleAreaStop && t.End > e.VisibleAreaStart) e.SuggestedVisibility = System.Windows.Visibility.Visible; else e.SuggestedVisibility = System.Windows.Visibility.Collapsed; } }
The easiest way to decide if it should be on screen is like above: If the start is smaller than stop of view AND the stop is bigger than start of view. This covers the cases when time items are partly on screen, and when time items span the whole screen and beyond.
Summary
If you have large datasets like 1000 rows and 1000 time items per row – you really have to follow these guidelines. But you see good effects long before that.
Below 1 million Time items – Gantt still renders fast.
GTP.NET.SL 2.11.24
Problem with UserDrawn TimeItems not being measured correctly fixed
GTP.NET.SL 2.11.10
ShowWeekNumbers setting exposed on DateScaler. This is useful when UseDayNumbersNotWeeks==false and you want to display a date interval for the week (false) or the week number for the year (true)
GTP.NET.SL 2.10.7.46
Issue with non updating link when collapsing grid node fixed
GTP.NET.SL 2.9.21.43
TimeItemLinkStyle changed to dependency property to enable binding
Fixed issue with Foreground,Background not always getting invalidated when it should
GTP.NET.SL 2.4.7.2
.net4
Gesture support to move time items and scroll and zoom datescaler
Autoscroll when out of view (time wise)
GTP.NET.SL 2.4.5.22
——————————————
——-GTP.NET.SL 2.4.5.22—-
——————————————
keygtpnetsl.pfx (2)
Gantt_WPF.2010.csproj (5)
Added editable gridcells
keygtpnetsl.pfx (2)
Gantt.cs (56)
DispatcherTimer used by Gantt cleaned up after use