I developed a control to sort and order modules in a document. This is done in a telerik treeview control.
This works fine in Sharepoint 2010. Now I have the requirement to deploy this to Sharepoint 2013, but the site collection is running in "2010 compatibility mode". What happens now is, the page is loaded and I see all the controls. But after the second, sometimes the third click on any button in the treeview (does not affect other standard buttons on the page), the control disappears when trying to rebind. The code behind is executed, but in the browser console (same behaviour in IE/FF) I see errors like
IE: window._WebForm_InitCallback() -> (SCRIPT438: Object doesn't support this
property or method )
FF: init.js -> too much recursion
The control is still "available" in the page source, but seems not to be able to draw itself again. I added screenshots to show the control before and after. The browser shows a long list of maybe 100 entries "WebForm_Initcallback, init.js. This is probably the "too much recursion shown in the javascript debugger.
I started with a 2011 Telerik.Web.UI control version, since this is an old project, but on seeing the error, updated to the latest version 2014.1.225.35. This solution works fine in Sharepoint 2010, and Sharepoint 2013 (site collection in non-compat mode)
I can't pinpoint the error, since it's thrown in minified sharepoint javascript files. Has anyone experienced this problem before?
ASPX
Code Behind
This works fine in Sharepoint 2010. Now I have the requirement to deploy this to Sharepoint 2013, but the site collection is running in "2010 compatibility mode". What happens now is, the page is loaded and I see all the controls. But after the second, sometimes the third click on any button in the treeview (does not affect other standard buttons on the page), the control disappears when trying to rebind. The code behind is executed, but in the browser console (same behaviour in IE/FF) I see errors like
IE: window._WebForm_InitCallback() -> (SCRIPT438: Object doesn't support this
property or method )
FF: init.js -> too much recursion
The control is still "available" in the page source, but seems not to be able to draw itself again. I added screenshots to show the control before and after. The browser shows a long list of maybe 100 entries "WebForm_Initcallback, init.js. This is probably the "too much recursion shown in the javascript debugger.
I started with a 2011 Telerik.Web.UI control version, since this is an old project, but on seeing the error, updated to the latest version 2014.1.225.35. This solution works fine in Sharepoint 2010, and Sharepoint 2013 (site collection in non-compat mode)
I can't pinpoint the error, since it's thrown in minified sharepoint javascript files. Has anyone experienced this problem before?
ASPX
<telerik:RadFormDecorator ID="FormDecorator1" runat="server" DecoratedControls="all" Skin="Telerik"></telerik:RadFormDecorator> <telerik:RadAjaxPanel ID="RadAjaxPanel1" LoadingPanelID="RadAjaxLoadingPanel1" runat="server"> <asp:Button ID="btnExpandAll" runat="server" onclick="btnExpandAll_Click" Text="<%$Resources:MSH_DocumentCreatorUI,ReportGenerator_ExpandButtonText%>"/> <telerik:RadTreeList runat="server" ID="RadTreeList1" DataKeyNames="ID" ParentDataKeyNames="ParentChapter" OnNeedDataSource="RadTreeList1_NeedDataSource" OnUpdateCommand="RadTreeList1_UpdateCommand" OnInsertCommand="RadTreeList1_InsertCommand" OnItemCommand="RadTreeList1_ItemCommand" OnItemDataBound="RadTreeList1_ItemDataBound" AutoGenerateColumns="false" EditMode="InPlace" OnDataBinding="RadTreeList1_DataBinding" GridLines="None" NoRecordsText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_NoRecordsText%>"> <Columns> <docCreator:CustomTreeListEditCommandColumn UniqueName="EditCommandColumn" ButtonType="ImageButton" InsertText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_SaveButtonText%>" AddRecordText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_AddButtonText%>" HeaderStyle-Width="200px" DeleteButtonImageUrl="/_layouts/Images/DocumentCreator/delete.png" DeleteButtonID="DeleteButton" DeleteButtonCommand="Delete" DeleteButtonText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_DeleteButtonText%>" UpButtonImageUrl="/_layouts/Images/DocumentCreator/up.png" UpButtonID="UpButton" UpButtonCommand="Up" UpButtonText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_MoveUpButtonText%>" DownButtonImageUrl="/_layouts/Images/DocumentCreator/down.png" DownButtonID="DownButton" DownButtonCommand="Down" DownButtonText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_MoveDownButtonText%>" LeftButtonImageUrl="/_layouts/Images/DocumentCreator/left.png" LeftButtonID="LeftButton" LeftButtonCommand="Left" LeftButtonText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_MoveLeftButtonText%>" RightButtonImageUrl="/_layouts/Images/DocumentCreator/right.png" RightButtonID="RightButton" RightButtonCommand="Right" RightButtonText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_MoveRightButtonText%>"> </docCreator:CustomTreeListEditCommandColumn> <telerik:TreeListTemplateColumn HeaderText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_ChapterNumberColumnHeaderText%>" ItemStyle-Width="70px" HeaderStyle-Width="70px" UniqueName="ChapterNumber"> <ItemTemplate> <asp:Label ID="lblChapterNumber" runat="server"></asp:Label> </ItemTemplate> <EditItemTemplate> <asp:Label ID="lblChapterNumber" runat="server"></asp:Label> </EditItemTemplate> </telerik:TreeListTemplateColumn> <telerik:TreeListBoundColumn DataField="Title" HeaderText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_TextColumnHeaderText%>" UniqueName="Title"> </telerik:TreeListBoundColumn> <telerik:TreeListTemplateColumn HeaderText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_LinkColumnHeaderText%>" UniqueName="Link"> <ItemTemplate> <asp:Repeater ID="textModulesRepeater" runat="server"> <ItemTemplate> <asp:HyperLink ID="lblLink" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Title") %>' NavigateUrl='<%# DataBinder.Eval(Container.DataItem, "Url") %>'></asp:HyperLink> <br /> </ItemTemplate> </asp:Repeater> </ItemTemplate> <EditItemTemplate> <div style="overflow: auto; width: 100%; max-height: 200px; position: relative;"> <asp:CheckBoxList ID="textModulesList" runat="server" CssClass="textModuleCheckboxList" /> </div> </EditItemTemplate> </telerik:TreeListTemplateColumn> <telerik:TreeListTemplateColumn HeaderText="<%$Resources:MSH_DocumentCreatorUI,ChapterEditor_StatusColumnHeaderText%>" UniqueName="Status"> <ItemTemplate> <asp:Image ID="Image1" ImageUrl='<%# this.GetImageUrlForColumnStatus(DataBinder.Eval(Container.DataItem, "Status")) %>' runat="server" /><asp:Label ID="lblStatus" Style="vertical-align: top; margin-left: 5px" runat="server" Text='<%# this.GetLabelForColumnStatus(DataBinder.Eval(Container.DataItem, "Status")) %>'></asp:Label> </ItemTemplate> <EditItemTemplate> <asp:DropDownList runat="server" ID="ddlStatus"> <asp:ListItem Text="<%$Resources:MSH_DocumentCreatorUI,StatusEnum_Green_Description%>" Value="Green"></asp:ListItem> <asp:ListItem Text="<%$Resources:MSH_DocumentCreatorUI,StatusEnum_Yellow_Description%>" Value="Yellow"></asp:ListItem> <asp:ListItem Text="<%$Resources:MSH_DocumentCreatorUI,StatusEnum_Red_Description%>" Value="Red" Selected="True"></asp:ListItem> </asp:DropDownList> </EditItemTemplate> </telerik:TreeListTemplateColumn> </Columns> </telerik:RadTreeList> </telerik:RadAjaxPanel> <telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" />Code Behind
using System;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Collections;using Microsoft.SharePoint;using System.Collections.Generic;using Microsoft.SharePoint.Linq;using Telerik.Web.UI;using System.Data;using System.Linq;using MSH.DocumentCreator.DataAccess;using MSH.DocumentCreator;using MSH.DocumentCreator.DocumentGeneration;namespace MSH.DocumentCreator.ChapterEditor{ public partial class ChapterEditorUserControl : UserControl { ReportStructure _docStructure; DataTable _textModules; IEnumerable<int> selectedTextModules; ReportStructure DocumentStructure { get { if (_docStructure == null) _docStructure = new ReportStructure(); return _docStructure; } } private Dictionary<int, double?> itemOrderMaxValuesByParent = new Dictionary<int, double?>(); private Dictionary<int, double?> itemOrderMinValuesByParent = new Dictionary<int, double?>(); private Dictionary<int, string> itemChapterNumber = new Dictionary<int, string>(); private Dictionary<int, int> chapterParentIds = new Dictionary<int, int>(); protected override void OnLoad(EventArgs e) { base.OnLoad(e); selectedTextModules = new List<int>(); foreach (ChaptersItem item in DocumentStructure.Chapters) { selectedTextModules = selectedTextModules.Union(item.LinkId.Select(l => l.Value)); } } protected void btnExpandAll_Click(object sender, EventArgs e) { RadTreeList1.ExpandAllItems(); } #region Commands protected void RadTreeList1_InsertCommand(object sender, TreeListCommandEventArgs e) { this.DocumentStructure.Chapters.InsertOnSubmit(GetChapter(e.Item as TreeListDataInsertItem)); this.DocumentStructure.SaveChapters(); } protected void RadTreeList1_UpdateCommand(object sender, TreeListCommandEventArgs e) { GetChapter(e.Item as TreeListDataItem); this.DocumentStructure.SaveChapters(); ReBind(); } public void RadTreeList1_ItemCommand(object sender, TreeListCommandEventArgs e) { if (e.CommandName == "InitInsert" || e.CommandName == "PerformInsert" || e.CommandName == "Edit" || e.CommandName == "Cancel") return; ChaptersItem currentItem = GetChapter(e.Item as TreeListDataItem); int id = (e.Item as TreeListDataItem).GetId("ID"); switch (e.CommandName) { case "Left": DocumentStructure.MoveLeft(currentItem); break; case "Right": DocumentStructure.MoveRight(currentItem); break; case "Up": DocumentStructure.MoveUp(currentItem); break; case "Down": DocumentStructure.MoveDown(currentItem); break; case "Delete": DocumentStructure.DeleteRecursively(currentItem); DocumentStructure.SaveChapters(); break; default: break; } RadTreeList1.Rebind(); } #endregion #region Binding protected void RadTreeList1_NeedDataSource(object sender, TreeListNeedDataSourceEventArgs e) { RadTreeList1.DataSource = DocumentStructure.Chapters.OrderBy(ch => ch.ItemOrder).ToList<ChaptersItem>(); } protected void RadTreeList1_DataBinding(object sender, EventArgs e) { ReportParts tm = new ReportParts(); _textModules = tm.GetByContentType("Text-Module", "Text Module"); } public void RadTreeList1_ItemDataBound(object sender, TreeListItemDataBoundEventArgs e) { if (e.Item is TreeListHeaderItem) { (e.Item.Controls[0].Controls[0] as Button).ToolTip = MSH.DocumentCreator.Modules.UIResources.MSH_DocumentCreatorUI.ChapterEditor_AddChapterText; } switch (e.Item.ItemType) { case TreeListItemType.EditItem: DropDownList ddlStatus = e.Item.FindControl("ddlStatus") as DropDownList; ChaptersItem spItem = null; if (e.Item is TreeListDataItem) spItem = this.DocumentStructure.GetChapter((e.Item as TreeListDataItem).GetId("ID")); if (spItem != null && spItem.Status.HasValue) ddlStatus.SelectedValue = spItem.Status.Value.ToString(); CheckBoxList chkListTextModules = e.Item.FindControl("textModulesList") as CheckBoxList; if (spItem != null) { var item = DocumentStructure.GetChapter(spItem.ID.Value); PopulateHierarchyDictionaries(item); } if (chkListTextModules != null) { chkListTextModules.DataSource = GetUnusedOrOwnTextModules(spItem == null ? null : spItem.LinkId); chkListTextModules.DataTextField = "Title"; chkListTextModules.DataValueField = "ID"; chkListTextModules.DataBind(); } if (spItem != null && spItem.LinkId != null && spItem.LinkId.Count != 0) { foreach (int? docId in spItem.LinkId) { foreach (ListItem item in chkListTextModules.Items) if (docId.Value.ToString() == item.Value) { item.Selected = true; } } } if (spItem != null) { Label lblChNumber = e.Item.FindControl("lblChapterNumber") as Label; lblChNumber.Text = itemChapterNumber[spItem.ID.Value]; } break; case TreeListItemType.Item: case TreeListItemType.AlternatingItem: int id = (e.Item as TreeListDataItem).GetId("ID"); var currentItem = DocumentStructure.GetChapter(id); var parentChapterId = currentItem.ParentChapter ?? -1; PopulateHierarchyDictionaries(currentItem); if (!itemOrderMinValuesByParent[parentChapterId].HasValue || itemOrderMinValuesByParent[parentChapterId] >= currentItem.ItemOrder) { ImageButton upButton = e.Item.FindControl("UpButton") as ImageButton; upButton.Enabled = false; upButton.ImageUrl = "/_layouts/Images/DocumentCreator/up_gray.png"; } if (!itemOrderMaxValuesByParent[parentChapterId].HasValue || itemOrderMaxValuesByParent[parentChapterId] <= currentItem.ItemOrder) { ImageButton downButton = e.Item.FindControl("DownButton") as ImageButton; downButton.Enabled = false; downButton.ImageUrl = "/_layouts/Images/DocumentCreator/down_gray.png"; } if (!currentItem.ParentChapter.HasValue) { ImageButton leftButton = e.Item.FindControl("LeftButton") as ImageButton; leftButton.Enabled = false; leftButton.ImageUrl = "/_layouts/Images/DocumentCreator/left_gray.png"; } if (!DocumentStructure.Chapters.Any(ch => ch.ParentChapter == currentItem.ParentChapter && ch.ItemOrder < currentItem.ItemOrder)) { ImageButton rightButton = e.Item.FindControl("RightButton") as ImageButton; rightButton.Enabled = false; rightButton.ImageUrl = "/_layouts/Images/DocumentCreator/right_gray.png"; } Repeater textModulesRepeater = e.Item.FindControl("textModulesRepeater") as Repeater; if (textModulesRepeater != null) { textModulesRepeater.DataSource = GetTextModulesWithCountry(currentItem.LinkId); textModulesRepeater.DataBind(); } Label lblNumber = e.Item.FindControl("lblChapterNumber") as Label; lblNumber.Text = itemChapterNumber[currentItem.ID.Value]; break; default: break; } } protected void checkBoxList_DataBound(object sender, EventArgs args) { CheckBoxList checkBoxes = sender as CheckBoxList; foreach (ListItem item in checkBoxes.Items) { item.Attributes.Add("Style", "padding: 0px !important;"); } } private void ReBind() { RadTreeList1.DataSource = this.DocumentStructure.Chapters.OrderBy(ch => ch.ItemOrder); RadTreeList1.DataBind(); } #endregion #region Helpers protected string GetImageUrlForColumnStatus(object status) { switch ((Status)status) { case Status.Red: return "/_layouts/Images/DocumentCreator/red_ball.png"; case Status.Green: return "/_layouts/Images/DocumentCreator/green_ball.png"; case Status.Yellow: return "/_layouts/Images/DocumentCreator/yellow_ball.png"; default: return string.Empty; } } protected string GetLabelForColumnStatus(object status) { return Helpers.GetDescription((Status)status); } private ChaptersItem GetChapter(TreeListDataItem item) { return GetChapterValues(item, item.ParentItem); } private ChaptersItem GetChapter(TreeListDataInsertItem item) { return GetChapterValues(item, item.ParentItem); } private ChaptersItem GetChapterValues(TreeListEditableItem item, TreeListDataItem parentItem) { int? id = null; ChaptersItem chapter = null; if (item is TreeListDataItem) { id = (item as TreeListDataItem).GetId("ID"); chapter = DocumentStructure.GetChapter(id.Value); } else chapter = new ChaptersItem(); chapter.ParentChapter = GetParentId(parentItem); Hashtable values = item.GetValues(); DropDownList ddlStatus = item.FindControl("ddlStatus") as DropDownList; if (ddlStatus != null) { Status statusValue = Status.None; if (ddlStatus.SelectedValue != null) statusValue = (Status)Enum.Parse(typeof(Status), ddlStatus.SelectedValue); chapter.Status = statusValue; } CheckBoxList chkListTextModules = item.FindControl("textModulesList") as CheckBoxList; if (chkListTextModules != null) { foreach (ListItem chkItem in chkListTextModules.Items) { int linkId = Int32.Parse(chkItem.Value); if (chkItem.Selected) { if (chapter.Status.Value == Status.Red) chapter.Status = Status.Yellow; if (chapter.LinkId.Count(v => v.Value == linkId) == 0) chapter.LinkId.Add(linkId); } else { if (chapter.LinkId.Count(v => v.Value == linkId) != 0) chapter.LinkId.Remove(chapter.LinkId.Where(v => v.Value == linkId).First()); } } } if (!chapter.ID.HasValue) chapter.ItemOrder = DocumentStructure.Chapters.Where(ch => ch.ParentChapter == chapter.ParentChapter).Max(ch => ch.ItemOrder) + 1 ?? 1; chapter.Title = values["Title"] as string; return chapter; } private int? GetParentId(TreeListDataItem parent) { if (parent == null) return null; ChaptersItem parentItem = this.DocumentStructure.GetChapter(parent.GetId("ID")); if (parentItem == null) return null; return parentItem.ID; } private string GetChapterNumber(ChaptersItem item) { if (!item.ParentChapter.HasValue) { return (chapterParentIds.Values.Count(v => v == -1) + 1).ToString(); } else { return itemChapterNumber[item.ParentChapter.Value] + "." + (chapterParentIds.Values.Count(v => v == item.ParentChapter.Value) + 1); } } private DataTable GetTextModulesWithCountry(IList<int?> ds) { DataTable result = new DataTable(); result.Columns.Add("ID"); result.Columns.Add("Title"); result.Columns.Add("URL"); if (ds != null) foreach (DataRow module in _textModules.Rows) { int moduleId = (int)module["ID"]; if (ds.FirstOrDefault(r => r.Value == moduleId) != null) { var tmEntity = DocumentStructure.TextModules.FirstOrDefault(tm => tm.ID == moduleId); if (tmEntity != null) result.Rows.Add(moduleId, module["Title"], tmEntity.Path + "/" + tmEntity.Name); } } return result; } private object GetUnusedOrOwnTextModules(IList<int?> ds) { DataTable result = new DataTable(); result.Columns.Add("ID"); result.Columns.Add("Title"); foreach (DataRow module in _textModules.Rows) { if ((ds != null && ds.FirstOrDefault(r => r.Value == (int)module["ID"]) != null) || !selectedTextModules.Contains((int)module["ID"])) result.Rows.Add(module["ID"], module["Title"]); } result.DefaultView.Sort = "Title"; return result.DefaultView; } private void PopulateHierarchyDictionaries(ChaptersItem item) { var parentChapterId = item.ParentChapter ?? -1; if (!itemOrderMaxValuesByParent.ContainsKey(parentChapterId)) itemOrderMaxValuesByParent.Add(parentChapterId, DocumentStructure.Chapters.Where(ch => ch.ParentChapter == item.ParentChapter).Max(ch1 => ch1.ItemOrder)); if (!itemOrderMinValuesByParent.ContainsKey(parentChapterId)) itemOrderMinValuesByParent.Add(parentChapterId, DocumentStructure.Chapters.Where(ch => ch.ParentChapter == item.ParentChapter).Min(ch1 => ch1.ItemOrder)); if (!itemChapterNumber.ContainsKey(item.ID.Value)) { itemChapterNumber.Add(item.ID.Value, GetChapterNumber(item)); } if (!chapterParentIds.ContainsKey(item.ID.Value)) { chapterParentIds.Add(item.ID.Value, parentChapterId); } } #endregion }}