Hi,
I have a treeview that shows account numbers in a hierarchy of account groups.
MultiSelect is on for the treeview.
Sometimes (not always), when I drop multiple items on an account group node a thread exception occurs.
I recently upgraded the RadControls from 'Q3 2011 SP1' to 'Q2 2012'. In the older version this problem did not exist. I did not change code, only the Telerik dll changed.
Some more details:
Message = Object reference not set to an instance of an object.
Stacktrace = at Telerik.WinControls.UI.TreeNodeElement.ApplyStyle()
at Telerik.WinControls.UI.TreeNodeElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
at Telerik.WinControls.RadObject.RaisePropertyNotifications(RadPropertyValue propVal, Object oldValue, Object newValue, ValueSource oldSource)
at Telerik.WinControls.RadObject.ResetValueCore(RadPropertyValue propVal, ValueResetFlags flags)
at Telerik.WinControls.UI.TreeNodeElement.Detach()
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.RemoveElement(Int32 position)
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.MeasureElements()
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureViewElement(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureView(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.UI.VirtualizedScrollPanel`2.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.RootRadElement.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RootRadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.Layouts.ContextLayoutManager.UpdateLayout()
at Telerik.WinControls.Layouts.ContextLayoutManager.UpdateLayoutCallback(ILayoutManager manager).
Relevant code:
I have a treeview that shows account numbers in a hierarchy of account groups.
MultiSelect is on for the treeview.
Sometimes (not always), when I drop multiple items on an account group node a thread exception occurs.
I recently upgraded the RadControls from 'Q3 2011 SP1' to 'Q2 2012'. In the older version this problem did not exist. I did not change code, only the Telerik dll changed.
Some more details:
Message = Object reference not set to an instance of an object.
Stacktrace = at Telerik.WinControls.UI.TreeNodeElement.ApplyStyle()
at Telerik.WinControls.UI.TreeNodeElement.OnPropertyChanged(RadPropertyChangedEventArgs e)
at Telerik.WinControls.RadObject.RaisePropertyNotifications(RadPropertyValue propVal, Object oldValue, Object newValue, ValueSource oldSource)
at Telerik.WinControls.RadObject.ResetValueCore(RadPropertyValue propVal, ValueResetFlags flags)
at Telerik.WinControls.UI.TreeNodeElement.Detach()
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.RemoveElement(Int32 position)
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.MeasureElements()
at Telerik.WinControls.UI.BaseVirtualizedContainer`1.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureViewElement(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureView(SizeF availableSize)
at Telerik.WinControls.UI.ScrollViewElement`1.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.UI.VirtualizedScrollPanel`2.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.RootRadElement.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RootRadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.Layouts.ContextLayoutManager.UpdateLayout()
at Telerik.WinControls.Layouts.ContextLayoutManager.UpdateLayoutCallback(ILayoutManager manager).
Relevant code:
public
partial
class
AccountGroupList : AccountsFormBase
{
public
AccountGroupList()
{
InitializeComponent();
accountGroupTreeView.NodeMouseDown += AccountGroupTreeViewNodeMouseDown;
accountGroupTreeView.DragStarting += AccountGroupTreeViewDragStarting;
accountGroupTreeView.DragOverNode += AccountGroupTreeViewDragOverNode;
accountGroupTreeView.DragEnding += AccountGroupTreeViewDragEnding;
accountGroupTreeView.ContextMenuStrip = contextMenuStrip;
accountGroupTreeView.AllowDragDrop =
true
;
accountGroupTreeView.MultiSelect =
true
;
}
protected
override
void
OnDataBind()
{
FillAccountGroupTreeView();
}
private
void
FillAccountGroupTreeView()
{
accountGroupTreeView.Nodes.Clear();
//find and add main account groups to tree
foreach
(AccountOrAccountGroupInfo mainAccountGroup
in
Model.AccountGroupHierarchy.Where(x => !x.EreportingId.HasValue && !x.ParentId.HasValue))
{
var mainAccountGroupNode =
new
AccountGroupNode(mainAccountGroup.AccountGroup,
true
) {Tag = mainAccountGroup};
//find and add sub account groups of main account group
foreach
(AccountOrAccountGroupInfo subAccountGroup
in
Model.AccountGroupHierarchy.Where(x => !x.EreportingId.HasValue && x.ParentId == mainAccountGroup.Id))
{
var subAccountNode =
new
AccountGroupNode(subAccountGroup.AccountGroup,
false
) { Tag = subAccountGroup };
//find and add ereporting accounts of sub account group
foreach
(AccountOrAccountGroupInfo eReportingAccount
in
Model.AccountGroupHierarchy.Where(x => x.EreportingId.HasValue && x.ParentId == subAccountGroup.Id))
{
var eReportingAccountNode =
new
EreportingAccountNode(eReportingAccount.AccountGroup)
{Tag = eReportingAccount, AllowDrop =
false
};
subAccountNode.Nodes.Add(eReportingAccountNode);
}
mainAccountGroupNode.Nodes.Add(subAccountNode);
}
//find and add ereporting accounts of main account group
foreach
(AccountOrAccountGroupInfo eReportingAccount
in
Model.AccountGroupHierarchy.Where(x => x.EreportingId.HasValue && x.ParentId == mainAccountGroup.Id))
{
var eReportingAccountNode =
new
EreportingAccountNode(eReportingAccount.AccountGroup) { Tag = eReportingAccount };
mainAccountGroupNode.Nodes.Add(eReportingAccountNode);
}
accountGroupTreeView.Nodes.Add(mainAccountGroupNode);
}
//find and add ereporting accounts that are not linked to an account group
foreach
(AccountOrAccountGroupInfo eReportingAccount
in
Model.AccountGroupHierarchy.Where(x => x.EreportingId.HasValue && !x.ParentId.HasValue))
{
var eReportingAccountNode =
new
EreportingAccountNode(eReportingAccount.AccountGroup) { Tag = eReportingAccount, AllowDrop =
false
};
accountGroupTreeView.Nodes.Add(eReportingAccountNode);
}
}
#region drag, drop, context menu
private
void
AccountGroupTreeViewDragStarting(
object
sender, RadTreeViewDragCancelEventArgs e)
{
try
{
//determine if dragging is allowed for selected node
if
(e.Node !=
null
)
{
//An ereporting account node can be dragged
var ereportingAccountNode = e.Node
as
EreportingAccountNode;
if
(ereportingAccountNode !=
null
)
{
e.Cancel =
false
;
}
else
{
//A group node can only be dragged if it has no child groups
var accountGroupNode = e.Node
as
AccountGroupNode;
if
(accountGroupNode !=
null
)
{
e.Cancel = (accountGroupNode.SubAccountGroupCount > 0);
}
else
{
e.Cancel =
true
;
}
}
}
else
{
e.Cancel =
true
;
}
}
catch
(Exception)
{
e.Cancel =
true
;
throw
;
}
}
private
void
AccountGroupTreeViewDragOverNode(
object
sender, RadTreeViewDragCancelEventArgs e)
{
try
{
//determine if the dragged node can be dropped on the current hovered node
if
(e.Node !=
null
)
{
var accountNode = e.Node
as
AccountNodeBase;
if
(accountNode !=
null
)
{
e.Cancel = !(accountNode.CanBeDroppedOnTarget(e.TargetNode));
}
else
{
e.Cancel =
true
;
}
}
else
{
e.Cancel =
true
;
}
}
catch
(Exception)
{
e.Cancel =
true
;
throw
;
}
}
private
void
AccountGroupTreeViewDragEnding(
object
sender, RadTreeViewDragCancelEventArgs e)
{
try
{
//recheck if it is correct to drop the dragged node on the target node (this event is fired multiple times when multiple nodes are dragged at once)
//execute the action that is expected
var accountNode = e.Node
as
AccountNodeBase;
if
(accountNode !=
null
)
{
if
(accountNode.CanBeDroppedOnTarget(e.TargetNode))
{
var draggedAccountGroupHierarchy = (AccountOrAccountGroupInfo)accountNode.Tag;
var targetAccountGroupHierarchy = ((AccountOrAccountGroupInfo)e.TargetNode.Tag);
if
(e.Node
is
EreportingAccountNode)
{
Controller.MoveEreportingAccountToAccountGroup(draggedAccountGroupHierarchy.Id, targetAccountGroupHierarchy.Id);
}
else
{
Controller.MoveAccountGroupUnderAccountGroup(draggedAccountGroupHierarchy.Id, targetAccountGroupHierarchy.Id);
}
}
else
{
e.Cancel =
true
;
}
}
else
{
e.Cancel =
true
;
}
}
catch
(Exception)
{
e.Cancel =
true
;
throw
;
}
}
#endregion
#region Tree Node classes
private
abstract
class
AccountNodeBase : RadTreeNode
{
protected
readonly
Font TreeNodeFont =
new
Font(
"Segoe UI"
, 8.25f);
public
abstract
bool
CanBeDroppedOnTarget(RadTreeNode target);
}
private
class
AccountGroupNode : AccountNodeBase
{
public
bool
IsRootNode {
get
;
private
set
; }
public
int
SubAccountGroupCount
{
get
{
return
Nodes.Count(o => o
is
AccountGroupNode); }
}
internal
AccountGroupNode(
string
text,
bool
isRootNode)
{
Font = TreeNodeFont;
Text = text;
IsRootNode = isRootNode;
}
public
override
bool
CanBeDroppedOnTarget(RadTreeNode target)
{
//a group node can be dropped on target if
// -the target is also a group node
// -the node has no child groups
// -the node is a main group (level 1)
// -the target node is not the current parent of the node
var targetNode = target
as
AccountGroupNode;
return
targetNode !=
null
&& SubAccountGroupCount == 0 && targetNode.IsRootNode && targetNode != Parent;
}
}
private
class
EreportingAccountNode : AccountNodeBase
{
internal
EreportingAccountNode(
string
text)
{
Font = TreeNodeFont;
Text = text;
}
public
override
bool
CanBeDroppedOnTarget(RadTreeNode target)
{
//an ereporting node can be dropped on any group node that is not the current parent of the ereporting node
if
(!(target
is
EreportingAccountNode) && target != Parent)
{
return
true
;
}
return
false
;
}
}
#endregion
}