[NullReferenceException: Object reference not set to an instance of an object.] Telerik.Web.UI.TreeListItemDecorator.PrepareDataItemsServiceCells(RadTreeList owner) +534 Telerik.Web.UI.RadTreeList.PrepareRows() +215 Telerik.Web.UI.RadTreeList.Render(HtmlTextWriter writer) +29 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8 System.Web.UI.Control.Render(HtmlTextWriter writer) +10 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8 System.Web.DynamicData.DynamicControl.Render(HtmlTextWriter writer) +154 ...
Here is the code:
<%@ Control Language="C#" CodeBehind="ManyToMany_Edit.ascx.cs" Inherits="Ctp.U.Web.ResidentPortal.Forms.ManyToMany_EditField" %><%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %><telerik:RadTreeList ID="_radTreeList1" runat="server" OnDataBound="_radTreeList1_DataBound"></telerik:RadTreeList>using System;using System.Collections;using System.ComponentModel;using System.Data.Objects;using System.Data.Objects.DataClasses;using System.Web.DynamicData;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace Ctp.U.Web.ResidentPortal.Forms{ public partial class ManyToMany_EditField : System.Web.DynamicData.FieldTemplateUserControl { public void Page_Load(object sender, EventArgs e) { // Register for the DataSource's updating event EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl(); // This field template is used both for Editing and Inserting ds.Updating += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting); ds.Inserting += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting); } void DataSource_UpdatingOrInserting(object sender, EntityDataSourceChangingEventArgs e) { MetaTable childTable = ChildrenColumn.ChildTable; // Comments assume employee/territory for illustration, but the code is generic // Get the collection of territories for this employee RelatedEnd entityCollection = (RelatedEnd)Column.EntityTypeProperty.GetValue(e.Entity, null); // In Edit mode, make sure it's loaded (doesn't make sense in Insert mode) if (Mode == DataBoundControlMode.Edit && !entityCollection.IsLoaded) { entityCollection.Load(); } // Get an IList from it (i.e. the list of territories for the current employee) // REVIEW: we should be using EntityCollection directly, but EF doesn't have a // non generic type for it. They will add this in vnext IList entityList = ((IListSource)entityCollection).GetList(); // Go through all the territories (not just those for this employee) foreach (object childEntity in childTable.GetQuery(e.Context)) { // Check if the employee currently has this territory bool isCurrentlyInList = entityList.Contains(childEntity); // Find the checkbox for this territory, which gives us the new state string pkString = childTable.GetPrimaryKeyString(childEntity); //ListItem listItem = CheckBoxList1.Items.FindByValue(pkString); TreeListDataItem radItem = null; foreach (TreeListDataItem item in _radTreeList1.Items) { if (item["Id"].Text == pkString) radItem = item; } if (radItem == null) continue; // If the states differs, make the appropriate add/remove change if (radItem.Selected) { if (!isCurrentlyInList) entityList.Add(childEntity); } else { if (isCurrentlyInList) entityList.Remove(childEntity); } } } protected void DataBound() { MetaTable childTable = ChildrenColumn.ChildTable; // Comments assume employee/territory for illustration, but the code is generic IList entityList = null; ObjectContext objectContext = null; if (Mode == DataBoundControlMode.Edit) { object entity; ICustomTypeDescriptor rowDescriptor = Row as ICustomTypeDescriptor; if (rowDescriptor != null) { // Get the real entity from the wrapper entity = rowDescriptor.GetPropertyOwner(null); } else { entity = Row; } // Get the collection of territories for this employee and make sure it's loaded RelatedEnd entityCollection = Column.EntityTypeProperty.GetValue(entity, null) as RelatedEnd; if (entityCollection == null) { throw new InvalidOperationException(String.Format("The ManyToMany template does not support the collection type of the '{0}' column on the '{1}' table.", Column.Name, Table.Name)); } if (!entityCollection.IsLoaded) { entityCollection.Load(); } // Get an IList from it (i.e. the list of territories for the current employee) // REVIEW: we should be using EntityCollection directly, but EF doesn't have a // non generic type for it. They will add this in vnext entityList = ((IListSource)entityCollection).GetList(); // Get the current ObjectContext // REVIEW: this is quite a dirty way of doing this. Look for better alternative ObjectQuery objectQuery = (ObjectQuery)entityCollection.GetType().GetMethod( "CreateSourceQuery").Invoke(entityCollection, null); objectContext = objectQuery.Context; } // Go through all the territories (not just those for this employee) foreach (object childEntity in childTable.GetQuery(objectContext)) { _radTreeList1.DataKeyNames = new string[] { "Id" }; _radTreeList1.ParentDataKeyNames = new string[] { "ParentId" }; TreeListDataItem radItem = new TreeListDataItem(_radTreeList1 , TreeListItemType.Item , _radTreeList1.Items.Count , true); radItem.DataItem = childEntity; // Make it selected if the current employee has that territory if (Mode == DataBoundControlMode.Edit) { radItem.Selected = entityList.Contains(childEntity); } _radTreeList1.Items.Add(radItem); } } protected void _radTreeList1_DataBound(object sender, EventArgs e) { DataBound(); } public override Control DataControl { get { return _radTreeList1; } } }}