[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;
}
}
}
}