I am trying to draw timelines in WPF. It should basically consist of 3 rectangles.
It should look something like this (hardcoded using XAML): Timeline
The large white rectangle should fill all of the available space, the green rectangles represent the start and duration of events which happen on the timeline.
The models representing this is a TimeLineEvent class which has a TimeSpan start and a timespan duration to represent when the event starts and how long it lasts (in ticks or seconds or whatever). There is also a TimeLine class which has an ObservableCollection which holds all of the events on the timeline. It also has a TimeSpan duration which represents how long the timeline itself is.
What I need to do is to be able to dynamically draw the events (green rectangles) on the timeline based on their duration and start, and the ratios between these so that an event is drawn corresponding to when it occurs and for how long. There can be more than one event on a timeline.
My approach so far has been to make a TimeLine.xaml file which just holds a canvas element. In the code-behind file I have overriden the OnRender method to draw these rectangles, which works with hardcoded values.
In the MainWindow.xaml I have created a datatemplate and set the datatype to TimeLine:
<DataTemplate x:Key="TimeLineEventsTemplate" DataType="{x:Type local:TimeLine}">
<Border>
<local:TimeLine Background="Transparent"/>
</Border>
</DataTemplate>
Have tried different settings for this, but not sure what I am doing to be honest. I then have a stackpanel which contains a listbox that is using my datatemplate and binding TimeLines, which is an ObservableCollection holding TimeLine objects, in my MainWindow code-behind.
<StackPanel Grid.Column="1" Grid.Row="0">
<ListBox x:Name="listBox"
Margin="20 20 20 0"
Background="Transparent"
ItemTemplate="{StaticResource TimeLineEventsTemplate}"
ItemsSource="{Binding TimeLines}"/>
</StackPanel>
This draws new timelines when I create new Timeline objects, looking like this: Timelines
The problem with this is that it does not render the green rectangles properly, to do this I need to know the width of the white rectangle, so that I can use the ratios of the different duration to translate to a position. The problem seems to be that the width property is 0 when the OnRender method is called. I have tried overriding OnRenderSizeChanged, as shown here: In WPF how can I get the rendered size of a control before it actually renders? I have seen in my debug printing that OnRender first gets called, then OnRenderSizeChanged and then I get the OnRender to run again by calling this.InvalidateVisual(); in the override. All the width properties I can get out are still always 0 though which is strange because I can see that it gets rendered and has a size. Have also tried the Measure and Arrange overrides as shown in other posts but have not been able to get out a value other than 0 so far.
So how can I dynamically draw rectangles on the timeline with correct position and size?
Sorry if I am missing something obvious here, I have just been working with WPF for a week now and I don't have anyone to ask. Let me know if you would like to see some more code samples. Any help is appreciated :).