we need this so that every timeline band can have it's own instance and therefore different brush and event top coordinates and width
Inheritance: System.Windows.Controls.ContentControl, INotifyPropertyChanged
        public object CreateEvent(
            TimelineEvent e,
            TimelineDisplayEvent de
            )
        {
            FrameworkElement element;

            Debug.Assert(e != null);

            if (m_elementPool.Count == 0)
            {
                element = CreateEventElement() as FrameworkElement;
            }
            else
            {
                element = m_elementPool.Pop() as FrameworkElement;
            }

            element.DataContext = de;
            element.SetValue(Canvas.ZIndexProperty, (e.Row + 1) * MIN_EVENT_ZINDEX);
            m_canvas.Children.Add(element);

            if (m_parent.IsMainBand)
            {
                m_parent.TimelineTray.FireEventCreated(element, de);
                m_parent.FireEventCreated(element, de);
            }

            return(element);
        }
 internal void FireEventCreated(
     FrameworkElement element,
     TimelineDisplayEvent de
     )
 {
     if (OnEventCreated != null)
     {
         OnEventCreated(element, de);
     }
 }
 internal void FireOnEventVisible(
     FrameworkElement element,
     TimelineDisplayEvent de
     )
 {
     if (OnEventVisible != null)
     {
         OnEventVisible(element, de);
     }
 }
        ///
        /// <summary>
        /// Calculate top position and width of each event</summary>
        ///
        public void CalculateEventPositions(
            )
        {
            TimelineDisplayEvent pos;
            double maxWidth = 0;

            Debug.Assert(AllEvents != null);

            if (m_dispEvents == null)
            {
                return;
            }

            Utilities.Trace(this);

            foreach (TimelineEvent e in AllEvents)
            {
                if (!m_dispEvents.ContainsKey(e))
                {
                    pos = new TimelineDisplayEvent(e, m_parent.TimelineTray, this);
                    m_dispEvents.Add(e, pos);
                }
                else
                {
                    pos = m_dispEvents[e];
                }

                Debug.Assert(e.Row >= 0, "Need first call CalculateEventRows for main band");

                if (pos.Top == -1 || pos.TimelineTray.RecalculateEventTopPosition)
                {
                    pos.SetCalculatedTop(e.Row * m_maxEventHeight + TOP_MARGIN);
                }

                pos.Recalculate(false);

                maxWidth = Math.Max(maxWidth, pos.DescriptionWidth);
            }

            m_maxDescriptionWidth = PixelsToTimeSpan(maxWidth);
        }
        internal void FireEventCreated(
			FrameworkElement element,
			TimelineDisplayEvent de
		)
        {
            if (OnEventCreated != null)
            {
                OnEventCreated(element, de);
            }
        }
 internal void FireOnEventVisible(
     FrameworkElement                            element,
     TimelineDisplayEvent                        de
 )
 {
     if (OnEventVisible != null)
     {
         OnEventVisible(element, de);
     }
 }
        ///
        /// <summary>
        /// After current data is changed this function fixes positions of all columns
        /// and all events</summary>
        ///
        private void FixPositions(
            bool displayEvents,
            bool animate        = false,
            bool updateDuration = false
            )
        {
            double startLeft;
            double posOffset;

            int  colcount;
            long newStart;
            long idxOffset;

            colcount  = (m_columnCount + EXTRA_COLUMNS);
            posOffset = TimeSpanToPixels(CurrentDateTime - m_timeline.GetFloorTime(CurrentDateTime));

            newStart = m_timeline.IndexOf(CurrentDateTime) - colcount / 2;
            //newStart = m_timeline.IndexOf(CurrentDateTime);

            startLeft = (PixelWidth / 2 - ColumnPixelWidth * (colcount / 2)) - posOffset;
            //startLeft = 0;

            if (m_startIndex == INVALID_COLUMN_IDX || newStart > m_startIndex + colcount || newStart + colcount < m_startIndex)
            {
                //
                // this is case when we draw columns for the first time, or there are no columns which data contexts
                // may be reused
                //
                PositionColumnAndMarker(newStart, startLeft, 0, true, null);
            }
            else if (m_startIndex == newStart)
            {
                //
                // this is the case when we reuse existing column context (date string)
                //
                PositionColumnAndMarker(newStart, startLeft, 0, false, null);
            }
            else
            {
                idxOffset = m_startIndex - newStart;

                ShiftArray(m_columns, idxOffset, out m_columns);
                ShiftArray(m_columnMarkers, idxOffset, out m_columnMarkers);

                PositionColumnAndMarker(newStart, startLeft, 0, false, null);

                if (idxOffset > 0)
                {
                    for (int i = 0; i < idxOffset; ++i)
                    {
                        SetColumnDataContext(newStart + i, i);
                    }
                }
                else
                {
                    for (int i = colcount + (int)idxOffset; i < colcount; ++i)
                    {
                        SetColumnDataContext(newStart + i, i);
                    }
                }
            }
            m_startIndex = Math.Max(0, newStart);
            //m_startIndex = 0;

            if (displayEvents)
            {
                DisplayEvents(animate);
            }

            if (updateDuration)
            {
                foreach (var ve in m_visibleEvents)
                {
                    var evnt = ve.Key;
                    TimelineDisplayEvent tde = m_dispEvents[evnt];

                    tde.Recalculate();
                }
            }
        }