/// <summary>
        /// Draw the three with the give draw function
        /// </summary>
        /// <param name="defaultDrawFunc">default draw function, draw the component when specify tage draw function not exists</param>
        public void Draw(float x, float y, DrawNodeFunc defaultDrawFunc, Dictionary <string, DrawNodeFunc> themeDictionary = null)
        {
            if (defaultDrawFunc == null && themeDictionary == null)
            {
                throw new ArgumentNullException("defaultDrawFunc");
            }

            DrawRecursive(x, y, root, defaultDrawFunc, themeDictionary);
        }
        void DrawRecursive(float x, float y, Node node, DrawNodeFunc defaultDrawFunc, Dictionary <string, DrawNodeFunc> themeDictionary)
        {
            if (node == null)
            {
                return;
            }

            var contextAttr = GetNodeRuntimeAttribute(node);
            var drawFunc    = themeDictionary != null &&
                              themeDictionary.TryGetValue(contextAttr.template.TagName, out var specifyDrawFunc)
                ? specifyDrawFunc : defaultDrawFunc;

            if (drawFunc != null)
            {
                var nc = node.Context; // protected node.Context

                var attributes = new Dictionary <string, object>(contextAttr.attributes.Count
                                                                 + contextAttr.template.attributes.Count);

                foreach (var kv in contextAttr.template.attributes)
                {
                    attributes[kv.Key] = kv.Value;
                }
                foreach (var kv in contextAttr.attributes)
                {
                    attributes[kv.Key.TargetName] = kv.Value;
                }

                defaultDrawFunc(x + node.LayoutGetLeft(), y + node.LayoutGetTop(),
                                node.LayoutGetWidth(), node.LayoutGetHeight(),
                                contextAttr.textDataBindExpressCurrentValue,
                                attributes // contextAttr.attributes ???
                                );
                if (!(nc == null && node.Context == null) && nc != node.Context)
                {
                    throw new Exception("cant change node.Context !");
                }
                node.Context = nc; // protected node.Context
            }

            foreach (var child in node.Children)
            {
                DrawRecursive(x + node.LayoutGetLeft(), y + node.LayoutGetTop(), child, defaultDrawFunc, themeDictionary);
            }
        }