/// <summary>
 /// Process items if IsDirty == true.
 /// </summary>
 /// <param name="idsrc">The context.</param>
 public void Render(IDataSourceRenderContext idsrc)
 {
     if (IsDirty)
     {
         RenderPipeline(idsrc);
     }
 }
        /// <summary>
        /// Process the items through the list of <see cref="IDataSourceRenderer"/>.
        /// Default impl.
        /// </summary>
        /// <param name="idsrc">Render context. icrc.Area is set to Rect.Empty.</param>
        protected virtual void RenderPipeline(IDataSourceRenderContext idsrc)
        {
            _trace.Verbose($"RenderPipeline {Name} i:{Items} c:{_renderers.Count}");
            if (Items == null)
            {
                return;
            }
            if (_renderers.Count == 0)
            {
                return;
            }
            var pmap = new Dictionary <IDataSourceRenderer, object>();

            // Phase I: init each renderer; it may opt-out by returning NULL
            foreach (var idsr in _renderers)
            {
                var state = idsr.Preamble(idsrc);
                // TODO may want an exception instead
                if (state != null)
                {
                    pmap.Add(idsr, state);
                }
            }
            if (pmap.Count > 0)
            {
                // Phase II: traverse the data and distribute to renderers
                int ix = 0;
                foreach (var item in Items)
                {
                    foreach (var idsr in _renderers)
                    {
                        if (pmap.TryGetValue(idsr, out object state))
                        {
                            idsr.Render(state, ix, item);
                        }
                    }
                    ix++;
                }
                // Phase IIIa: post-traversal render bookkeeping
                foreach (var idsr in _renderers)
                {
                    if (pmap.TryGetValue(idsr, out object state))
                    {
                        idsr.RenderComplete(state);
                    }
                }
                // Phase IV: finalize renderers
                foreach (var idsr in _renderers)
                {
                    if (pmap.TryGetValue(idsr, out object state))
                    {
                        idsr.Postamble(state);
                    }
                }
            }
            Clean();
        }