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 }