Hi
I have a timeline that shows events with a start date and a duration during a year.
I would like the timeline to center its events and zoom in to them when the user selects a year in an externa control.
The scale and scroll gets set and the timeline updates, but it is not correctley showing all the entries, the scroll is slightly of center from the events on the timeline.
I have made a sample project that shows the algorithm used and the scenario that I have attached to this post and also added a image showing how the scroll gets offset.
Once i have set found the earliest and latest (starttime + duration) datetime of the events in the timeline I use the following method to center the ScrollPosition and set the ScrollScale to cover all events.
public void UpdateTimeLineScroll(DateTime minItemDate, DateTime maxItemDate) { if (minItemDate == DateTime.MinValue || maxItemDate == DateTime.MinValue) { return; } // Check so that we are not out of scope if (minItemDate < igDateTimeAxis.ActualMinimum) minItemDate = igDateTimeAxis.ActualMinimum; if (maxItemDate > igDateTimeAxis.ActualMaximum) maxItemDate = igDateTimeAxis.ActualMaximum; // Calculate the relative sizes double span = (maxItemDate - minItemDate).Ticks; double minSpan = (minItemDate - igDateTimeAxis.ActualMinimum).Ticks; double range = (igDateTimeAxis.ActualMaximum - igDateTimeAxis.ActualMinimum).Ticks; double middle = minSpan + (span / 2); // Just to be save, don't divide by zero if (range == 0) return; double newScrollPosition = middle / range; // Add 0.05 to make it just a little larger then the content double newScrollScale = span / range + 0.05; // Update scroll position and scale to zoom in to content igDateTimeAxis.ScrollScale = newScrollScale; igDateTimeAxis.ScrollPosition = newScrollPosition; }
Hi Hannes,
Looking thru your sample I see that in your CenterContent function your reference to FirstOrDefault appears to be assuming that your first record is the earliest record based on DueDate. I think you will need to sort the records first.
var sortData = Data.OrderBy(x => x.DueDate);
Then I’m not sure if you want to reference the duration of the first sorted item because you are trying to center on one item or you might need to also identify the last record in the sorted values so that you have the minimum and maximum values across all records.
HI Marianne
The first and last date are correct as they are (surely you can find them in a more efficient way, but this works for me). It is the other algorithm that I can’t wrap my head around why it does’nt work as expected, why the offset in scrollPosition?!?
thanks
Hello Hannes,
I took a look at your sample and I believe the reason the scroll position is offset is because the algorithm is assuming the scroll position is the center point of the zoombar's slider. This isn't the case however. The scroll position is offset left or right by a certain amount depending on which half of the timeline the slider lies. You can see this if you check the ScrollPosition property when the slider is placed all the way to the left and to the right. When the slider is up against the left side it shows 0, but visually, the center of the slider is not at 0. The same thing with the right side. The algorithm does not take this into account and I can't say for sure how much you should offset it by as the amount varies depending on how deeply to the right or left the slider lies.
The easiest and more appropriate way, in my opinion, is to set the slider directly rather than using the DateTimeAxis.ScrollPosition. The XamTimeline control gives you access to the XamZoombar through the Zoombar property. The zoombar exposes a Range property which contains a Minimum and Maximum. These correspond to the left and right sides of the slider so you can control the exact position of the slider. Figuring out these values is easy since you already calculated them in your algorithm. The following code would do the trick.
// Update scroll position and scale to zoom in to content. (the 0.05 is to make it just a little larger then the content) xamTimeline1.Zoombar.Range.Minimum = (minSpan / range) - 0.05; xamTimeline1.Zoombar.Range.Maximum = ((minSpan + span) / range) + 0.05;
I've attached an updated version of your sample. Let me know if you have any questions on this.
Thank you for the help!
This solved it for me and the timeline it now working as expected.
Best regards!
Hannes