private static MvcHtmlString _cond <T, F>(
            this HtmlHelper <T> htmlHelper,
            Expression <Func <T, F> > expression,
            ExternalContainerType itemsContainer = ExternalContainerType.koComment,
            object htmlAttributes = null,
            string afterRender    = null,
            bool negateCondition  = false,
            string format         = null,
            params LambdaExpression[] otherExpressions)
        {
            if (expression == null)
            {
                throw (new ArgumentNullException("expression"));
            }
            IDictionary <string, object> attributes = null;

            if (htmlAttributes == null)
            {
                attributes = new RouteValueDictionary();
            }
            else if (htmlAttributes is IDictionary <string, object> )
            {
                attributes = htmlAttributes as IDictionary <string, object>;
            }
            else
            {
                attributes = new RouteValueDictionary(htmlAttributes);
            }
            IBindingsBuilder <T> bindings = htmlHelper.ClientBindings();

            if (bindings == null)
            {
                throw (new ArgumentNullException("bindings"));
            }
            string bindingsValue = string.Format(
                ifScript,
                bindings.standardString(negateCondition ? "ifnot" : "if", expression, format, otherExpressions),
                bindings.ValidationType == "UnobtrusiveClient" ? "true" : "false",
                afterRender == null ? "null" : afterRender);

            if (attributes.ContainsKey("data-bind"))
            {
                attributes["data-bind"] = (attributes["data-bind"] as string) + ", " + bindingsValue;
            }
            else
            {
                attributes["data-bind"] = bindingsValue;
            }
            attributes["data-nobinding"] = "true";
            string openTag;
            string closeTag;

            BasicHtmlHelper.GetContainerTags(itemsContainer, attributes, out openTag, out closeTag);
            htmlPush("_ClientControlsFlowStack_", closeTag);
            return(MvcHtmlString.Create(
                       openTag
                       ));
        }
        private static int TreeViewRec <VM, T> (
            StringBuilder sb,
            StringBuilder sbInit,
            bool editMode,
            HtmlHelper <VM> htmlHelper,
            RenderInfo <IEnumerable <T> > renderInfo,
            Func <int, string> collectionName,
            ExternalContainerType itemContainer,
            string rootClass,
            object[] itemTemplates,
            Func <object, int, int> itemTemplateSelector,
            Func <int, string> itemClassSelector,
            Func <object, int, TreeViewItemStatus> itemStatus,
            float opacity,
            bool canMove,
            int level,
            int totalCount,
            string fatherName,
            string root_id)
        {
            string basicId = BasicHtmlHelper.IdFromName(fatherName);



            sbInit.Append(renderInfo.PartialRendering);

            IDictionary <string, object> htmlAttributesContainer = new Dictionary <string, object>();

            string externalOpenTag  = null;
            string externalCloseTag = null;
            string handleClass      = basicId + "_handle";

            htmlAttributesContainer["id"] = basicId + "_ItemsContainer";
            if (level == 0)
            {
                htmlAttributesContainer["class"] = rootClass + "  mvcct-items-container";
                rootClass = null;
            }
            else
            {
                if (rootClass != null)
                {
                    htmlAttributesContainer["class"] = rootClass + "_  mvcct-items-container";
                }
            }
            BasicHtmlHelper.GetContainerTags(ExternalContainerType.ul, htmlAttributesContainer, out externalOpenTag, out externalCloseTag);
            sb.Append(externalOpenTag);

            IEnumerable list = renderInfo.Model as IEnumerable;

            if (list == null)
            {
                list = new List <T>();
            }

            string javasctiptOpacity = string.Empty;
            int    sonIndex          = -1;;

            foreach (object o in list)
            {
                if (o == null)
                {
                    continue;
                }
                totalCount++;
                sonIndex++;
                int    templateIndex   = itemTemplateSelector(o, level);
                object initialTemplate = itemTemplates[templateIndex];
                string initCollection  = collectionName(templateIndex);


                TreeViewItemStatus status = itemStatus(o, level);
                if (initCollection == null)
                {
                    status = TreeViewItemStatus.Hide;
                }
                ITreeViewNodeContainer wrapper  = null;
                IUpdateModel           uWrapper = null;
                bool closed = isClosed(status, o, htmlHelper);
                Type type   = TemplateInvoker <string> .ExtractModelType(initialTemplate);

                if (editMode)
                {
                    wrapper =
                        typeof(TreeViewUpdater <string>).GetGenericTypeDefinition()
                        .MakeGenericType(new Type[] { type })
                        .GetConstructor(new Type[0])
                        .Invoke(new object[0]) as ITreeViewNodeContainer;
                    uWrapper = wrapper as IUpdateModel;
                    uWrapper.ImportFromModel(o, null, null, new object[] { closed });
                }
                else
                {
                    wrapper  = new TreeViewUpdater <T>(false);
                    uWrapper = wrapper as IUpdateModel;
                }



                string prefix        = renderInfo.Prefix;
                string partialPrefix = renderInfo.PartialPrefix;
                if (editMode)
                {
                    sbInit.Append(
                        BasicHtmlHelper.RenderUpdateInfoI(htmlHelper, uWrapper, ref partialPrefix, new string[0]));
                }
                else
                {
                    BasicHtmlHelper.RenderUpdateInfoI(htmlHelper, uWrapper, ref partialPrefix, new string[0], noOutput: true);
                }
                prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);
                if (level == 0)
                {
                    wrapper.FatherOriginalId = null;
                }
                else
                {
                    wrapper.FatherOriginalId = fatherName;
                }
                wrapper.OriginalId        = prefix;
                wrapper.PositionAsSon     = sonIndex;
                wrapper.SonNumber         = 0;
                wrapper.SonCollectionName = null;
                string itemOpenTag  = null;
                string itemCloseTag = null;

                string innerItemOpenTag  = null;
                string innerItemCloseTag = null;

                htmlAttributesContainer["id"]    = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "Container"));
                htmlAttributesContainer["class"] = closed ? "closed" : "open";
                BasicHtmlHelper.GetContainerTags(ExternalContainerType.li, htmlAttributesContainer, out itemOpenTag, out itemCloseTag);

                htmlAttributesContainer["id"]    = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item_SubContainer"));
                htmlAttributesContainer["class"] = handleClass;
                BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesContainer, out innerItemOpenTag, out innerItemCloseTag);


                bool         hasCollection = true;
                string       name          = initCollection;
                PropertyInfo property      = null;
                if (name == null)
                {
                    hasCollection = false;
                }
                else
                {
                    property      = o.GetType().GetProperty(name);
                    hasCollection = typeof(IEnumerable).IsAssignableFrom(property.PropertyType);
                }
                sb.Append(itemOpenTag);

                if (canMove && hasCollection)
                {
                    sb.Append(string.Format("<input  type='checkbox' class ='level-select_{0} level-select' />", root_id));
                }
                sb.Append(innerItemOpenTag);
                sb.Append(
                    (typeof(TemplateInvoker <string>)
                     .GetGenericTypeDefinition()
                     .MakeGenericType(new Type[] { type })
                     .GetConstructor(new Type[] { typeof(object) })
                     .Invoke(new object[] { initialTemplate }) as ITemplateInvoker)
                    .Invoke(htmlHelper, o, BasicHtmlHelper.AddField(prefix, "$.Item")));
                sb.Append(innerItemCloseTag);

                if (hasCollection)
                {
                    string currItemClass = itemClassSelector == null ?
                                           null :
                                           itemClassSelector(templateIndex);
                    if (currItemClass != null)
                    {
                        currItemClass = currItemClass.Trim() + "_" + BasicHtmlHelper.IdFromName(renderInfo.Prefix);
                    }
                    ICollection innerItem   = property.GetValue(o, new object[0]) as ICollection;
                    Type        listType    = property.PropertyType.GetGenericArguments()[0];
                    Type        allListType = typeof(IEnumerable <string>).GetGenericTypeDefinition().MakeGenericType(listType);
                    if (innerItem == null)
                    {
                        innerItem = allListType.GetConstructor(new Type[0]).Invoke(new object[0]) as ICollection;
                    }
                    wrapper.SonNumber         = innerItem.Count;
                    wrapper.SonCollectionName = initCollection;
                    if (editMode)
                    {
                        RenderWrapper <VM>(htmlHelper, partialPrefix, wrapper, sbInit);
                    }

                    totalCount = (int)typeof(TreeViewHelpers).GetMethod("TreeViewRec", BindingFlags.Static | BindingFlags.NonPublic).
                                 MakeGenericMethod(new Type[] { typeof(VM), listType })
                                 .Invoke(null, new object[]
                                         { sb,
                                           sbInit,
                                           editMode,
                                           htmlHelper,
                                           typeof(RenderInfo <string>).GetGenericTypeDefinition().MakeGenericType(allListType)
                                           .GetConstructor(new Type[] { typeof(string), typeof(string), typeof(string), allListType })
                                           .Invoke
                                               (new object[] {
                            renderInfo.Prefix,
                            renderInfo.PartialPrefix,
                            string.Empty,
                            innerItem
                        }),
                                           collectionName,
                                           itemContainer,
                                           currItemClass,
                                           itemTemplates,
                                           itemTemplateSelector,
                                           itemClassSelector,
                                           itemStatus,
                                           opacity,
                                           canMove,
                                           level + 1,
                                           totalCount,
                                           prefix,
                                           root_id });
                }
                else
                {
                    if (editMode)
                    {
                        RenderWrapper <VM>(htmlHelper, partialPrefix, wrapper, sbInit);
                    }
                }
                sb.Append(itemCloseTag);
            }


            if (canMove)
            {
                if (opacity > 1f)
                {
                    opacity = 1f;
                }
                else if (opacity < 0.01f)
                {
                    opacity = 0.01f;
                }

                if (opacity < 1f)
                {
                    javasctiptOpacity = string.Format(" opacity: {0}, ", opacity.ToString(CultureInfo.InvariantCulture));
                }
                string javascriptRootClass = string.Empty;
                if (rootClass != null)
                {
                    javascriptRootClass = string.Format(" connectWith: '.{0}', ", rootClass);
                }
                if (level > 0)
                {
                    sbInit.Append(string.Format(startScriptFormat,
                                                basicId,
                                                javasctiptOpacity,
                                                javascriptRootClass,
                                                root_id));
                }
            }
            else
            {
                if (level > 0)
                {
                    sbInit.Append(string.Format(startScriptNoMoveFormat,
                                                basicId,
                                                root_id));
                }
            }
            sb.Append(externalCloseTag);


            return(totalCount);
        }
        private static void TreeViewTop <VM, T>(
            StringBuilder sb,
            bool editMode,
            HtmlHelper <VM> htmlHelper,
            RenderInfo <IEnumerable <T> > renderInfo,
            Func <int, string> collectionName,
            ExternalContainerType itemContainer,
            string rootClass,
            object[] itemTemplates,
            Func <object, int, int> itemTemplateSelector,
            Func <int, string> itemClassSelector,
            Func <object, int, TreeViewItemStatus> itemStatus,
            float opacity,
            bool canMove,
            bool canAdd,
            TreeViewOptions treeViewOptions)
        {
            if (rootClass == null)
            {
                rootClass = defaultRootClass;
            }


            RenderInfo <TreeViewDisplay <T> > branchesRenderInfo = htmlHelper.InvokeTransform(renderInfo, new TreeViewDisplay <T>());

            if (editMode)
            {
                sb.Append(branchesRenderInfo.PartialRendering);
            }

            renderInfo.Prefix        = BasicHtmlHelper.AddField(branchesRenderInfo.Prefix, "flattened");
            renderInfo.PartialPrefix = BasicHtmlHelper.AddField(branchesRenderInfo.PartialPrefix, "flattened");

            StringBuilder sbInit = new StringBuilder();

            sbInit.Append(treeViewOptions.Render(renderInfo.Prefix));
            string basic_id = BasicHtmlHelper.IdFromName(renderInfo.Prefix);
            int    res      = TreeViewRec <VM, T>(
                sb,
                sbInit,
                editMode,
                htmlHelper,
                renderInfo,
                collectionName,
                itemContainer,
                rootClass,
                itemTemplates,
                itemTemplateSelector,
                itemClassSelector,
                itemStatus,
                opacity,
                canMove,
                0,
                0,
                basic_id,
                basic_id);

            if (canAdd)
            {
                StringBuilder templatesId      = new StringBuilder();
                string        myTemplateSymbol = BasicHtmlHelper.GetUniqueSymbol(htmlHelper, templateSymbol);
                sb.AppendFormat("<div id='{0}_Templates'>", basic_id);
                int templateIndex = -1;
                IDictionary <string, object> htmlAttributesContainer = new Dictionary <string, object>();
                foreach (object template in itemTemplates)
                {
                    templateIndex++;
                    Type type = TemplateInvoker <string> .ExtractModelType(template);

                    string initCollection = collectionName(templateIndex);

                    ITreeViewNodeContainer wrapper =
                        typeof(TreeViewUpdater <string>).GetGenericTypeDefinition()
                        .MakeGenericType(new Type[] { type })
                        .GetConstructor(new Type[0])
                        .Invoke(new object[0]) as ITreeViewNodeContainer;


                    bool closed = false;
                    (wrapper as IUpdateModel).ImportFromModel(null, null, null, new object[] { closed });

                    string prefix        = renderInfo.Prefix;
                    string partialPrefix = renderInfo.PartialPrefix;
                    string updater       = BasicHtmlHelper.RenderUpdateInfoI(
                        htmlHelper, wrapper as IUpdateModel,
                        ref partialPrefix, new string[0], myTemplateSymbol + templateIndex.ToString());

                    prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);



                    wrapper.FatherOriginalId  = string.Empty;
                    wrapper.OriginalId        = prefix;
                    wrapper.PositionAsSon     = 0;
                    wrapper.SonNumber         = 0;
                    wrapper.SonCollectionName = initCollection;
                    wrapper.Closed            = false;
                    string itemOpenTag  = null;
                    string itemCloseTag = null;

                    string innerItemOpenTag  = null;
                    string innerItemCloseTag = null;

                    string templateId       = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "Container"));
                    string templateUniqueId = templateId + templateIndex.ToString();
                    addTemplateId(templatesId, templateUniqueId);
                    htmlAttributesContainer["id"]    = templateId;
                    htmlAttributesContainer["class"] = closed ? "closed" : "open";
                    BasicHtmlHelper.GetContainerTags(ExternalContainerType.li, htmlAttributesContainer, out itemOpenTag, out itemCloseTag);

                    htmlAttributesContainer["id"]    = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item_SubContainer"));
                    htmlAttributesContainer["class"] = string.Empty;
                    BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesContainer, out innerItemOpenTag, out innerItemCloseTag);

                    bool hasCollection = true;

                    PropertyInfo property = null;
                    if (initCollection == null)
                    {
                        hasCollection = false;
                    }
                    else
                    {
                        property      = type.GetProperty(initCollection);
                        hasCollection = typeof(IEnumerable).IsAssignableFrom(property.PropertyType);
                    }
                    sb.Append(string.Format("<span id='{0}' style='display:none' class='MVCCT_EncodedTemplate'>", templateUniqueId));
                    StringBuilder itemSb = new StringBuilder();
                    itemSb.Append(itemOpenTag);

                    if (canMove && hasCollection)
                    {
                        itemSb.Append(string.Format("<input  type='checkbox' class ='level-select_{0} level-select' />", basic_id));
                    }
                    itemSb.Append(innerItemOpenTag);

                    itemSb.Append(
                        (typeof(TemplateInvoker <string>)
                         .GetGenericTypeDefinition()
                         .MakeGenericType(new Type[] { type })
                         .GetConstructor(new Type[] { typeof(object) })
                         .Invoke(new object[] { template }) as ITemplateInvoker)
                        .Invoke(htmlHelper, null, BasicHtmlHelper.AddField(prefix, "$.Item")));
                    itemSb.Append(innerItemCloseTag);

                    itemSb.Append(string.Format("<span class= 'MvcCT_init_info_{0}'>", basic_id));
                    itemSb.Append(updater);
                    RenderWrapper <VM>(htmlHelper, partialPrefix, wrapper, itemSb);
                    itemSb.Append("</span>");

                    if (hasCollection)
                    {
                        string base_id       = BasicHtmlHelper.IdFromName(prefix);
                        string currItemClass = itemClassSelector == null ?
                                               null :
                                               itemClassSelector(templateIndex);
                        if (currItemClass != null)
                        {
                            currItemClass = currItemClass + "_" + basic_id;
                        }
                        else
                        {
                            currItemClass = string.Empty;
                        }
                        string externalOpenTag  = null;
                        string externalCloseTag = null;
                        htmlAttributesContainer["id"] = base_id + "_ItemsContainer";

                        htmlAttributesContainer["class"] = currItemClass + " mvcct-items-container";

                        BasicHtmlHelper.GetContainerTags(ExternalContainerType.ul, htmlAttributesContainer, out externalOpenTag, out externalCloseTag);

                        itemSb.Append(externalOpenTag);
                        itemSb.Append(externalCloseTag);
                        if (canMove)
                        {
                            string javasctiptOpacity = string.Empty;
                            if (opacity > 1f)
                            {
                                opacity = 1f;
                            }
                            else if (opacity < 0.01f)
                            {
                                opacity = 0.01f;
                            }

                            if (opacity < 1f)
                            {
                                javasctiptOpacity = string.Format(" opacity: {0}, ", opacity.ToString(CultureInfo.InvariantCulture));
                            }
                            string javascriptRootClass = string.Empty;
                            if (currItemClass != null)
                            {
                                javascriptRootClass = string.Format(" connectWith: '.{0}', ", currItemClass);
                            }

                            itemSb.Append(string.Format(startScriptFormat,
                                                        base_id,
                                                        javasctiptOpacity,
                                                        javascriptRootClass,
                                                        basic_id));
                        }
                    }
                    itemSb.Append(itemCloseTag);
                    sb.Append(htmlHelper.Encode(itemSb.ToString()));
                    sb.Append("</span>");
                }
                sb.Append("</div>");
                sb.AppendFormat(
                    startTemplateScriptFormat,
                    basic_id, canMove ? "true" : "false",
                    myTemplateSymbol,
                    templatesId.ToString());
            }
            if (editMode)
            {
                sbInit.Append(htmlHelper.Hidden(BasicHtmlHelper.AddField(renderInfo.PartialPrefix, "$.ItemsCount"),
                                                res).ToString());
            }
            if (canMove)
            {
                sbInit.Append(string.Format(levelSelection, basic_id));
            }
            sb.Append(sbInit.ToString());
        }
        public static MvcHtmlString SortableListFor <VM, TItem>(
            this HtmlHelper <VM> htmlHelper,
            RenderInfo <IEnumerable <TItem> > renderInfo,
            object template,
            object addElementTemplate = null,
            float opacity             = 1,
            bool canSort = true,
            IDictionary <string, object> htmlAttributesContainer = null,
            IDictionary <string, object> htmlAttributesItems     = null,
            bool enableMultipleInsert               = true,
            ExternalContainerType itemContainer     = ExternalContainerType.li,
            ExternalContainerType allItemsContainer = ExternalContainerType.ul,
            object headerTemplate = null,
            object footerTemplate = null,
            string itemCss        = null,
            string altItemCss     = null,
            bool displayOnly      = false,
            string sortableHandle = null,
            Func <TItem, int> templateSelector = null,
            Func <int, IDictionary <string, object> > htmlAttributesSelector = null
            )
        {
            if (template == null)
            {
                throw (new ArgumentNullException("template"));
            }
            if (renderInfo == null)
            {
                throw (new ArgumentNullException("renderiNFO"));
            }
            if (string.IsNullOrWhiteSpace(itemCss))
            {
                itemCss = string.Empty;
            }
            if (string.IsNullOrWhiteSpace(altItemCss))
            {
                altItemCss = string.Empty;
            }
            if (displayOnly)
            {
                canSort = false;
            }
            if (canSort)
            {
                itemContainer     = ExternalContainerType.li;
                allItemsContainer = ExternalContainerType.ul;
                headerTemplate    = null;
                footerTemplate    = null;
                htmlHelper.ViewData[renderInfo.Prefix + "_Rendering"] = "SortableList_Dragging";
            }
            else
            {
                htmlHelper.ViewData[renderInfo.Prefix + "_Rendering"] = "SortableList_Dragging";
            }
            bool multipleTemplates = false;

            if (template is string || !(template is object[]))
            {
                template = new object[] { template };
            }
            else if (templateSelector != null)
            {
                multipleTemplates = true;
            }
            int nTemplates = (template as object[]).Length;

            Type[] allTypes = new Type[nTemplates];
            int    tcount   = 0;

            foreach (object t in (template as object[]))
            {
                if (t is string)
                {
                    allTypes[tcount] = typeof(TItem);
                }
                else
                {
                    allTypes[tcount] = TemplateInvoker <string> .ExtractModelType(t);
                }
                tcount++;
            }
            StringBuilder sb     = new StringBuilder();
            StringBuilder sbInit = new StringBuilder();

            sbInit.Append(renderInfo.PartialRendering);
            if (htmlAttributesContainer == null)
            {
                htmlAttributesContainer = new Dictionary <string, object>();
            }
            htmlAttributesContainer["id"] = BasicHtmlHelper.IdFromName(renderInfo.Prefix) + "_ItemsContainer";
            string externalOpenTag  = null;
            string externalCloseTag = null;
            string itemOpenTag      = null;
            string itemCloseTag     = null;

            BasicHtmlHelper.GetContainerTags(allItemsContainer, htmlAttributesContainer, out externalOpenTag, out externalCloseTag);
            sb.Append(externalOpenTag);

            if (htmlAttributesItems == null)
            {
                htmlAttributesItems = new Dictionary <string, object>();
            }
            IDictionary <string, object> fixedHtmlAttributesItems = htmlAttributesItems;
            bool   templateEnabled     = false;
            string addItemScriptFormat = addItemJQueryScriptFormat;

            switch (MvcEnvironment.Validation(htmlHelper))
            {
            case ValidationType.StandardClient:  break;

            case ValidationType.UnobtrusiveClient:  templateEnabled = true; break;

            default:  templateEnabled = true; break;
            }

            templateEnabled = templateEnabled && enableMultipleInsert;
            int    totalCount               = 0;
            string javasctiptOpacity        = string.Empty;
            string javascriptHandle         = string.Empty;
            string permutationElementPrefix = null;

            if (renderInfo.Model == null)
            {
                renderInfo.Model = new List <TItem>();
            }
            if (renderInfo.Model != null)
            {
                if (headerTemplate != null)
                {
                    if (multipleTemplates)
                    {
                        htmlAttributesItems = dictionarySelection(htmlAttributesSelector, fixedHtmlAttributesItems, -1);
                    }
                    ViewDataDictionary <TItem> dataDictionary = new ViewDataDictionary <TItem>();
                    dataDictionary.TemplateInfo.HtmlFieldPrefix = renderInfo.Prefix;
                    if (htmlHelper.ViewData.ContainsKey("ThemeParams"))
                    {
                        dataDictionary["ThemeParams"] = htmlHelper.ViewData["ThemeParams"];
                    }
                    BasicHtmlHelper.CopyRelevantErrors(dataDictionary.ModelState, htmlHelper.ViewData.ModelState, dataDictionary.TemplateInfo.HtmlFieldPrefix);
                    htmlAttributesItems["id"] = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(renderInfo.Prefix, "Header"));
                    BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesItems, out itemOpenTag, out itemCloseTag);
                    sb.Append(itemOpenTag);
                    sb.Append(new TemplateInvoker <TItem>(headerTemplate).Invoke <VM>(htmlHelper, dataDictionary));
                    sb.Append(itemCloseTag);
                }
                foreach (TItem x in renderInfo.Model)
                {
                    if (x == null && htmlHelper.ViewContext.ViewData.ModelState.IsValid)
                    {
                        continue;
                    }
                    totalCount++;
                    int  templateIndex = 0;
                    Type currType      = typeof(TItem);
                    if (multipleTemplates)
                    {
                        templateIndex       = templateSelector(x);
                        currType            = allTypes[templateIndex];
                        htmlAttributesItems = dictionarySelection(htmlAttributesSelector, fixedHtmlAttributesItems, templateIndex);
                    }
                    IUpdateModel um = null;
                    if (x == null)
                    {
                        um = typeof(AutoEnumerableUpdater <string>).GetGenericTypeDefinition().MakeGenericType(currType)
                             .GetConstructor(new Type[0]).Invoke(new object[0]) as IUpdateModel;
                    }
                    else if (x.GetType() == typeof(TItem))
                    {
                        um = new AutoEnumerableUpdater <TItem>();
                    }
                    else
                    {
                        um = typeof(AutoEnumerableUpdater <string>).GetGenericTypeDefinition().MakeGenericType(x.GetType())
                             .GetConstructor(new Type[0]).Invoke(new object[0]) as IUpdateModel;
                    }
                    um.ImportFromModel(x, null, null, new object[0]);
                    string prefix        = renderInfo.Prefix;
                    string partialPrefix = renderInfo.PartialPrefix;
                    string updateInfo    = BasicHtmlHelper.RenderUpdateInfo <TItem>(htmlHelper, um, ref partialPrefix, new string[0]);
                    if (!displayOnly)
                    {
                        sbInit.Append(updateInfo);
                    }
                    prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);
                    object currTemplate = (template as object[])[templateIndex];

                    ViewDataDictionary dataDictionary = null;
                    ITemplateInvoker   currInvoker    = null;
                    if (allTypes[templateIndex] == typeof(TItem))
                    {
                        dataDictionary = new ViewDataDictionary <TItem>(x);
                        currInvoker    = new TemplateInvoker <TItem>(currTemplate);
                    }
                    else
                    {
                        dataDictionary = typeof(ViewDataDictionary <string>).GetGenericTypeDefinition().MakeGenericType(allTypes[templateIndex])
                                         .GetConstructor(new Type[] { allTypes[templateIndex] }).Invoke(new object[] { x }) as ViewDataDictionary;

                        currInvoker = typeof(TemplateInvoker <string>).GetGenericTypeDefinition().MakeGenericType(allTypes[templateIndex])
                                      .GetConstructor(new Type[] { typeof(object) }).Invoke(new object[] { currTemplate }) as ITemplateInvoker;
                    }
                    dataDictionary.TemplateInfo.HtmlFieldPrefix = BasicHtmlHelper.AddField(prefix, "$.Item");
                    if (htmlHelper.ViewData.ContainsKey("ThemeParams"))
                    {
                        dataDictionary["ThemeParams"] = htmlHelper.ViewData["ThemeParams"];
                    }
                    BasicHtmlHelper.CopyRelevantErrors(dataDictionary.ModelState, htmlHelper.ViewData.ModelState, dataDictionary.TemplateInfo.HtmlFieldPrefix);
                    htmlAttributesItems["id"] = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item")) + "_Container";
                    BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesItems, out itemOpenTag, out itemCloseTag);
                    sb.Append(itemOpenTag);
                    sb.Append(currInvoker.Invoke <VM>(htmlHelper, dataDictionary));
                    sb.Append(itemCloseTag);
                }
            }
            string delayedRendering = null;

            if (addElementTemplate != null && !templateEnabled)
            {
                EnumerableUpdater <TItem> um = new EnumerableUpdater <TItem>(true);
                string prefix        = renderInfo.Prefix;
                string partialPrefix = renderInfo.PartialPrefix;
                sbInit.Append(
                    BasicHtmlHelper.RenderUpdateInfo <TItem>(htmlHelper, um, ref partialPrefix, new string[0]));
                prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);
                sbInit.Append(htmlHelper.GenericInput(InputType.Hidden,
                                                      BasicHtmlHelper.AddField(partialPrefix, "$.Deleted"), um.Deleted, null));
                delayedRendering = string.Format(
                    addItemScriptFormat,
                    BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item.InnerContainer")));
                ViewDataDictionary <TItem> dataDictionary = new ViewDataDictionary <TItem>(um.Item);
                dataDictionary.TemplateInfo.HtmlFieldPrefix = BasicHtmlHelper.AddField(prefix, "$.Item");
                if (htmlHelper.ViewData.ContainsKey("ThemeParams"))
                {
                    dataDictionary["ThemeParams"] = htmlHelper.ViewData["ThemeParams"];
                }
                BasicHtmlHelper.CopyRelevantErrors(dataDictionary.ModelState, htmlHelper.ViewData.ModelState, dataDictionary.TemplateInfo.HtmlFieldPrefix);
                htmlAttributesItems["id"] = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item")) + "_Container";

                BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesItems, out itemOpenTag, out itemCloseTag);
                sb.Append(itemOpenTag);
                sb.Append(new TemplateInvoker <TItem>(addElementTemplate).Invoke <VM>(htmlHelper, dataDictionary));
                sb.Append(itemCloseTag);
            }
            if (canSort)
            {
                PermutationsUpdater <TItem> um = new PermutationsUpdater <TItem>();
                um.ImportFromModel(null, null, null, new object[0]);
                string prefix        = renderInfo.Prefix;
                string partialPrefix = renderInfo.PartialPrefix;
                sbInit.Append(
                    BasicHtmlHelper.RenderUpdateInfo <TItem>(htmlHelper, um, ref partialPrefix, new string[0]));
                prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);
                sbInit.Append(
                    string.Format("<input type='hidden' id={0} name={1} value=''/>",
                                  BasicHtmlHelper.IdFromName(renderInfo.Prefix + "_Permutation"),
                                  BasicHtmlHelper.AddField(prefix, "$.Permutation")));
                if (opacity > 1f)
                {
                    opacity = 1f;
                }
                else if (opacity < 0.01f)
                {
                    opacity = 0.01f;
                }

                if (opacity < 1f)
                {
                    javasctiptOpacity = string.Format(" opacity: {0}, ", opacity.ToString(CultureInfo.InvariantCulture));
                }
                if (sortableHandle != null)
                {
                    javascriptHandle = string.Format(" handle: '{0}', ", sortableHandle);
                }
                permutationElementPrefix = prefix;
            }
            if (footerTemplate != null)
            {
                if (multipleTemplates)
                {
                    htmlAttributesItems = dictionarySelection(htmlAttributesSelector, fixedHtmlAttributesItems, -2);
                }
                ViewDataDictionary <TItem> dataDictionary = new ViewDataDictionary <TItem>();
                dataDictionary.TemplateInfo.HtmlFieldPrefix = renderInfo.Prefix;
                if (htmlHelper.ViewData.ContainsKey("ThemeParams"))
                {
                    dataDictionary["ThemeParams"] = htmlHelper.ViewData["ThemeParams"];
                }
                BasicHtmlHelper.CopyRelevantErrors(dataDictionary.ModelState, htmlHelper.ViewData.ModelState, dataDictionary.TemplateInfo.HtmlFieldPrefix);
                htmlAttributesItems["id"] = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(renderInfo.Prefix, "Footer"));
                BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesItems, out itemOpenTag, out itemCloseTag);
                sb.Append(itemOpenTag);
                sb.Append(new TemplateInvoker <TItem>(footerTemplate).Invoke <VM>(htmlHelper, dataDictionary));
                sb.Append(itemCloseTag);
            }
            if (templateEnabled)
            {
                IUpdateModel  um                  = null;
                TItem         dummyItem           = default(TItem);
                object[]      allTemplates        = template as object[];
                StringBuilder alltemplateNames    = new StringBuilder();
                StringBuilder allhiddenNames      = new StringBuilder();
                StringBuilder allsymbolNames      = new StringBuilder();
                string        basicTemplateSymbol = BasicHtmlHelper.GetUniqueSymbol(htmlHelper, templateSymbol);
                for (int i = 0; i < allTemplates.Length; i++)
                {
                    if (multipleTemplates)
                    {
                        htmlAttributesItems = dictionarySelection(htmlAttributesSelector, fixedHtmlAttributesItems, i);
                    }
                    if (allTypes[i] == typeof(TItem))
                    {
                        um = new AutoEnumerableUpdater <TItem>();
                    }
                    else
                    {
                        um = typeof(AutoEnumerableUpdater <string>).GetGenericTypeDefinition().MakeGenericType(allTypes[i])
                             .GetConstructor(new Type[0]).Invoke(new object[0]) as IUpdateModel;
                    }
                    string prefix           = renderInfo.Prefix;
                    string partialPrefix    = renderInfo.PartialPrefix;
                    string myTemplateSymbol = basicTemplateSymbol + i.ToString(CultureInfo.InvariantCulture);

                    sbInit.Append(
                        BasicHtmlHelper.RenderUpdateInfoI(htmlHelper, um, ref partialPrefix, new string[0], myTemplateSymbol));
                    prefix = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(partialPrefix);

                    ViewDataDictionary dataDictionary = null;
                    ITemplateInvoker   currInvoker    = null;
                    if (allTypes[i] == typeof(TItem))
                    {
                        dataDictionary = new ViewDataDictionary <TItem>(dummyItem);
                        currInvoker    = new TemplateInvoker <TItem>(allTemplates[i]);
                    }
                    else
                    {
                        dataDictionary = typeof(ViewDataDictionary <string>).GetGenericTypeDefinition().MakeGenericType(allTypes[i])
                                         .GetConstructor(new Type[] { allTypes[i] }).Invoke(new object[] { dummyItem }) as ViewDataDictionary;

                        currInvoker = typeof(TemplateInvoker <string>).GetGenericTypeDefinition().MakeGenericType(allTypes[i])
                                      .GetConstructor(new Type[] { typeof(object) }).Invoke(new object[] { allTemplates[i] }) as ITemplateInvoker;
                    }

                    dataDictionary.TemplateInfo.HtmlFieldPrefix = BasicHtmlHelper.AddField(prefix, "$.Item");
                    if (htmlHelper.ViewData.ContainsKey("ThemeParams"))
                    {
                        dataDictionary["ThemeParams"] = htmlHelper.ViewData["ThemeParams"];
                    }
                    BasicHtmlHelper.CopyRelevantErrors(dataDictionary.ModelState, htmlHelper.ViewData.ModelState, dataDictionary.TemplateInfo.HtmlFieldPrefix);


                    string templateId = BasicHtmlHelper.IdFromName(BasicHtmlHelper.AddField(prefix, "$.Item")) + "_Container";
                    htmlAttributesItems["id"] = templateId;
                    if (i > 0)
                    {
                        alltemplateNames.Append(", ");
                        allhiddenNames.Append(", ");
                        allsymbolNames.Append(", ");
                    }
                    alltemplateNames.Append("'");
                    alltemplateNames.Append(templateId);
                    alltemplateNames.Append("'");

                    allhiddenNames.Append("'");
                    allhiddenNames.Append(BasicHtmlHelper.IdFromName(prefix));
                    allhiddenNames.Append("'");

                    allsymbolNames.Append("/");
                    allsymbolNames.Append(myTemplateSymbol);
                    allsymbolNames.Append("/g");

                    BasicHtmlHelper.GetContainerTags(itemContainer, htmlAttributesItems, out itemOpenTag, out itemCloseTag);
                    sb.Append(string.Format("<span id='{0}' style='display:none' class='MVCCT_EncodedTemplate'>", templateId));
                    sb.Append(htmlHelper.Encode(itemOpenTag));
                    sb.Append(htmlHelper.Encode(currInvoker.Invoke <VM>(htmlHelper, dataDictionary)));
                    sb.Append(htmlHelper.Encode(itemCloseTag));
                    sb.Append("</span>");
                }

                sbInit.Append(string.Format(startTemplateScriptFormat, BasicHtmlHelper.IdFromName(renderInfo.Prefix),
                                            canSort ? "true" : "false", totalCount, allsymbolNames.ToString(), alltemplateNames.ToString(),
                                            allhiddenNames.ToString(), renderInfo.Prefix));
            }

            if (canSort)
            {
                sbInit.Append(string.Format(startScriptFormat, BasicHtmlHelper.IdFromName(renderInfo.Prefix), javascriptHandle + javasctiptOpacity, BasicHtmlHelper.IdFromName(permutationElementPrefix)));
            }
            string stylingJavaScript = string.Format(stylingScript, BasicHtmlHelper.IdFromName(renderInfo.Prefix), itemCss, altItemCss);

            sbInit.Append(stylingJavaScript);
            if (delayedRendering != null)
            {
                sbInit.Append(delayedRendering);
            }
            sb.Append(externalCloseTag);
            sbInit.Insert(0, sb.ToString());
            return(MvcHtmlString.Create(sbInit.ToString()));
        }
Exemple #5
0
        public static void DetailFormFor <VM, TItem>(
            this HtmlHelper <VM> htmlHelper,
            AjaxHelper <VM> ajax,
            RenderInfo <IEnumerable <Tracker <TItem> > > renderInfo,
            ExternalContainerType externalContainerType,
            string postActionName,
            string postControllerName,
            string detailPrefix     = null,
            string changedFieldCss  = null,
            string deletedRecordCss = null,
            IDictionary <string, object> externalContainerHtmlattributes = null,
            string clientOnSuccessEdit    = null,
            string clientOnFailureEdit    = null,
            string clientOnSuccessDisplay = null,
            string clientOnFailureDisplay = null,
            string loadingElementId       = null,
            Dialog detailDialog           = null
            )
            where TItem : class, new()
        {
            if (renderInfo == null)
            {
                throw (new ArgumentNullException("renderInfo"));
            }
            if (ajax == null)
            {
                throw (new ArgumentNullException("ajax"));
            }
            if (postActionName == null)
            {
                throw (new ArgumentNullException("postActionName"));
            }
            if (postControllerName == null)
            {
                throw (new ArgumentNullException("postControllerName"));
            }
            if (externalContainerHtmlattributes == null)
            {
                externalContainerHtmlattributes = new Dictionary <string, object>();
            }
            string baseName      = BasicHtmlHelper.IdFromName(renderInfo.Prefix);
            string formName      = baseName + "_AjaxForm";
            string containerName = baseName + "_Container";
            string onSuccessName = baseName + "_OnSuccess";
            string onFailureName = baseName + "_OnFailure";
            string onBeginName   = baseName + "_OnBegin";
            string beginTag;
            string closeTag;

            externalContainerHtmlattributes["id"] = containerName;
            BasicHtmlHelper.GetContainerTags(externalContainerType, externalContainerHtmlattributes, out beginTag, out closeTag);

            string javascriptChangedFieldCss  = changedFieldCss == null ? "null" : "'" + changedFieldCss + "'";
            string javascriptDeletedRecordCss = deletedRecordCss == null ? "null" : "'" + deletedRecordCss + "'";

            string javascriptClientOnSuccessEdit    = clientOnSuccessEdit == null ? "null" : "'" + clientOnSuccessEdit + "'";
            string javascriptClientOnSuccessDisplay = clientOnSuccessDisplay == null ? "null" : "'" + clientOnSuccessDisplay + "'";

            string javascriptClientOnFailureEdit    = clientOnFailureEdit == null ? "null" : "'" + clientOnFailureEdit + "'";
            string javascriptClientOnFailureDisplay = clientOnFailureDisplay == null ? "null" : "'" + clientOnFailureDisplay + "'";

            if (detailPrefix == null)
            {
                detailPrefix = string.Empty;
            }

            string validationType    = null;
            string unobtrusiveAjaxOn = "false";

            if (MvcEnvironment.UnobtrusiveAjaxOn(htmlHelper))
            {
                unobtrusiveAjaxOn = "true";
            }
            switch (MvcEnvironment.Validation(htmlHelper))
            {
            case ValidationType.StandardClient: validationType = "StandardClient"; break;

            case ValidationType.UnobtrusiveClient: validationType = "UnobtrusiveClient"; break;

            default: validationType = "Server"; break;
            }

            htmlHelper.ViewContext.Writer.Write(
                string.Format(prefixTranslationScript,
                              baseName,
                              BasicHtmlHelper.IdFromName(detailPrefix)));

            PropertyInfo[] propertiesToUpdate =
                BasicHtmlHelper.GetPropertiesForInput(typeof(TItem));

            StringBuilder sb = new StringBuilder();


            Stack <Type> recursionControl = new Stack <Type>();

            recursionControl.Push(typeof(TItem));
            getPropertiesToUpdate(
                sb,
                string.Empty,
                propertiesToUpdate,
                recursionControl);
            recursionControl.Pop();

            object formHtmlAttributes = null;

            if (formName != null)
            {
                formHtmlAttributes = new { id = formName };
            }
            htmlHelper.ViewContext.Writer.Write(
                string.Format(fieldsToUpdateScript, baseName, sb.ToString(), javascriptChangedFieldCss, javascriptDeletedRecordCss));
            htmlHelper.ViewContext.Writer.Write(
                string.Format(onBeginScript, onBeginName, baseName, "Edit", "null", loadingElementId, validationType));
            string dialogOpen;

            if (detailDialog == null)
            {
                dialogOpen = string.Empty;
            }
            else
            {
                dialogOpen = detailDialog.GetShow('#' + formName);
            }

            htmlHelper.ViewContext.Writer.Write(
                string.Format(onSuccessScript, onSuccessName, baseName, javascriptClientOnSuccessDisplay, javascriptClientOnSuccessEdit, dialogOpen, formName, validationType, unobtrusiveAjaxOn, containerName));
            htmlHelper.ViewContext.Writer.Write(
                string.Format(onFailureScript, onFailureName, baseName, javascriptClientOnFailureDisplay, javascriptClientOnFailureEdit));

            if (detailDialog != null)
            {
                htmlHelper.ViewContext.Writer.Write(detailDialog.GetCreation('#' + formName));
            }
            using (var form = ajax.BeginForm(
                       postActionName,
                       postControllerName,
                       new AjaxOptions()
            {
                HttpMethod = "Post",
                UpdateTargetId = unobtrusiveAjaxOn == "true" ? null : containerName,
                LoadingElementId = loadingElementId,
                OnSuccess = onSuccessName,
                OnBegin = onBeginName,
                OnFailure = onFailureName,
                InsertionMode = InsertionMode.Replace
            },
                       formHtmlAttributes))
            {
                htmlHelper.ViewContext.Writer.Write(beginTag);
                htmlHelper.ViewContext.Writer.Write(closeTag);
            }
            if (!MvcEnvironment.UnobtrusiveAjaxOn(htmlHelper))
            {
                htmlHelper.ViewContext.Writer.Write(
                    htmlHelper.AjaxSubmitEnabler(formName, false).ToString());
            }
        }
        public static HtmlHelper <F> _foreach <T, F>(
            this HtmlHelper <T> htmlHelper,
            Expression <Func <T, IEnumerable <F> > > expression,
            ExternalContainerType itemsContainer = ExternalContainerType.koComment,
            object htmlAttributes = null,
            string afterAdd       = null,
            string beforeRemove   = null,
            string afterRender    = null,
            string afterAllRender = null
            )
            where F : class
        {
            if (expression == null)
            {
                throw (new ArgumentNullException("expression"));
            }
            IDictionary <string, object> attributes = null;

            if (htmlAttributes == null)
            {
                attributes = new RouteValueDictionary();
            }
            else if (htmlAttributes is IDictionary <string, object> )
            {
                attributes = htmlAttributes as IDictionary <string, object>;
            }
            else
            {
                attributes = new RouteValueDictionary(htmlAttributes);
            }
            IBindingsBuilder <T> bindings = htmlHelper.ClientBindings();

            if (bindings == null)
            {
                throw (new ArgumentNullException("bindings"));
            }

            F    model     = default(F);
            Type basicType = typeof(F);

            if (basicType.IsClass)
            {
                var constructor = basicType.GetConstructor(new Type[0]);

                if (constructor != null)
                {
                    model = (F)constructor.Invoke(new object[0]);
                }
            }
            string bindingFieldName = bindings.GetFullBindingName(expression);
            string fieldName        = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));
            bool   nested;
            int    hl             = helperLevel(htmlHelper, out nested);
            string templateSymbol = ClientTemplateHelper.templateSymbol + hl.ToString();
            IBindingsBuilder <F> contentBindings = new BindingsBuilder <F>(htmlHelper.ViewContext.Writer, string.Empty,
                                                                           templateSymbol + ".A",
                                                                           bindings.ValidationType, null, htmlHelper);
            ViewDataDictionary <F> dic = new ViewDataDictionary <F>(model);

            dic["ClientBindings"]  = contentBindings;
            dic["_TemplateLevel_"] = hl;
            HttpContext.Current.Items["_TemplateLevel_" + hl.ToString()] = contentBindings;
            dic.TemplateInfo.HtmlFieldPrefix = templateSymbol + ".A";
            HtmlHelper <F> newHelper = new TemplateInvoker <F>().BuildHelper(htmlHelper, dic);

            string bindingsValue = string.Format(
                forScript,
                bindingFieldName,
                fieldName,
                BasicHtmlHelper.IdFromName(fieldName),
                templateSymbol,
                bindings.ValidationType == "UnobtrusiveClient" ? "true" : "false",
                afterAdd == null ? "null" : afterAdd,
                beforeRemove == null ? "null" : beforeRemove,
                afterRender == null ? "null" : afterRender,
                afterAllRender == null ? "null" : afterAllRender
                );

            if (attributes.ContainsKey("data-bind"))
            {
                attributes["data-bind"] = (attributes["data-bind"] as string) + ", " + bindingsValue;
            }
            else
            {
                attributes["data-bind"] = bindingsValue;
            }
            attributes["data-nobinding"] = "true";
            if (!nested && bindings.ValidationType == "UnobtrusiveClient")
            {
                bindings.AddServerErrors(fieldName);
            }
            string openTag;
            string closeTag;

            BasicHtmlHelper.GetContainerTags(itemsContainer, attributes, out openTag, out closeTag);
            htmlPush("_ClientControlsFlowStartStack_", openTag);
            htmlPush("_ClientControlsFlowStack_", closeTag);
            string innerHtml = string.Empty;

            return(newHelper);
        }
Exemple #7
0
        public static MvcHtmlString ClientBlockRepeater <T, F>(
            this HtmlHelper <T> htmlHelper,
            string templateName,
            Expression <Func <T, F> > expression,
            ExternalContainerType itemsContainer = ExternalContainerType.div,
            object htmlAttributes      = null,
            string afterAdd            = null,
            string beforeRemove        = null,
            string afterRender         = null,
            string afterAllRender      = null,
            object templateOptions     = null,
            bool applyClientValidation = true,
            bool fastNoJavaScript      = false,
            string templateEngine      = null
            )
            where T : class
        {
            if (expression == null)
            {
                throw (new ArgumentNullException("expression"));
            }
            if (string.IsNullOrWhiteSpace(templateName))
            {
                throw (new ArgumentNullException("templateName"));
            }
            IDictionary <string, object> attributes = null;

            if (htmlAttributes == null)
            {
                attributes = new RouteValueDictionary();
            }
            else if (htmlAttributes is IDictionary <string, object> )
            {
                attributes = htmlAttributes as IDictionary <string, object>;
            }
            else
            {
                attributes = new RouteValueDictionary(htmlAttributes);
            }
            bool writeTemplates           = !TemplatesStack.CheckTemplates();
            IBindingsBuilder <T> bindings = htmlHelper.ClientBindings();

            if (bindings == null)
            {
                throw (new ArgumentNullException("bindings"));
            }
            string templates = string.Empty;

            try
            {
                string bindingsValue = bindings.Template(
                    templateName,
                    expression,
                    afterAdd,
                    beforeRemove,
                    afterRender,
                    templateOptions,
                    null,
                    applyClientValidation,
                    fastNoJavaScript,
                    afterAllRender,
                    templateEngine).Get().ToString();

                if (attributes.ContainsKey("data-bind"))
                {
                    attributes["data-bind"] = (attributes["data-bind"] as string) + ", " + bindingsValue;
                }
                else
                {
                    attributes["data-bind"] = bindingsValue;
                }
                attributes["data-nobinding"] = "true";
            }
            finally
            {
                if (writeTemplates)
                {
                    templates = TemplatesStack.GetTemplates();
                }
            }
            string openTag;
            string closeTag;

            BasicHtmlHelper.GetContainerTags(itemsContainer, attributes, out openTag, out closeTag);
            return(MvcHtmlString.Create(openTag + closeTag + templates));
        }