This is a migrated thread and some comments may be shown as answers.

Moving items in a databound collection causes ArgumentOutofRangeException

18 Answers 270 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Chris
Top achievements
Rank 1
Chris asked on 18 May 2012, 04:05 PM
I have a RadTreeView databound as follows:

<telerik:RadTreeView Name="LayerTree" HorizontalAlignment="Stretch" 
     ItemsSource="{Binding Path=LayerTviVMList}" 
                                   ContextMenu="{StaticResource LayerTreeContextMenu}"
                                   IsVirtualizing="True" telerik:TreeViewPanel.VirtualizationMode="Recycling"
                                   telerik:AnimationManager.IsAnimationEnabled="False"
                                   SelectionMode="Multiple" BringIntoViewMode="Header" IsLineEnabled="True" ItemsIndent="15" />

Adding/Removing elements in LayerTviVMList works just fine. 

I have a collection of 5 elements, and when I do LayerTviVMList.Move(4,0) it appears that RadTreeView is throwing an ArgumentOutOfRangeException.

Below is the call stack:

  mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException() + 0x49 bytes
  mscorlib.dll!System.Collections.Generic.List<System.Windows.UIElement>.this[int].get(int index) + 0x2b bytes
  Telerik.Windows.Controls.Navigation.dll!Telerik.Windows.Controls.TreeView.TreeViewPanel.RemoveInternalChildRangeOverride(int startIndex, int count) Line 2863 + 0x13 bytes C#
  Telerik.Windows.Controls.Navigation.dll!Telerik.Windows.Controls.TreeView.TreeViewPanel.RemoveChildRange(System.Windows.Controls.Primitives.GeneratorPosition position, int itemCount, int itemUICount) Line 2350 + 0xf bytes C#
  Telerik.Windows.Controls.Navigation.dll!Telerik.Windows.Controls.TreeView.TreeViewPanel.OnItemsMove(System.Windows.Controls.Primitives.ItemsChangedEventArgs args) Line 2328 C#
  Telerik.Windows.Controls.Navigation.dll!Telerik.Windows.Controls.TreeView.TreeViewPanel.OnItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs args) Line 1821 C#
  PresentationFramework.dll!System.Windows.Controls.VirtualizingPanel.OnItemsChangedInternal(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs args) + 0x36 bytes
  PresentationFramework.dll!System.Windows.Controls.Panel.OnItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs args) + 0x28 bytes
  PresentationFramework.dll!System.Windows.Controls.ItemContainerGenerator.OnItemMoved(object item, int oldIndex, int newIndex) + 0x35d bytes
  PresentationFramework.dll!System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x11a bytes
  PresentationFramework.dll!System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(System.Type managerType, object sender, System.EventArgs e) + 0x5d bytes
  WindowsBase.dll!System.Windows.WeakEventManager.DeliverEventToList(object sender, System.EventArgs args, System.Windows.WeakEventManager.ListenerList list) + 0x5e bytes
  WindowsBase.dll!System.Windows.WeakEventManager.DeliverEvent(object sender, System.EventArgs args) + 0xd7 bytes
  WindowsBase.dll!System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0xa bytes
  PresentationFramework.dll!System.Windows.Data.CollectionView.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x29 bytes
  PresentationFramework.dll!System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(System.Type managerType, object sender, System.EventArgs e) + 0xe0 bytes
  WindowsBase.dll!System.Windows.WeakEventManager.DeliverEventToList(object sender, System.EventArgs args, System.Windows.WeakEventManager.ListenerList list) + 0x5e bytes
  WindowsBase.dll!System.Windows.WeakEventManager.DeliverEvent(object sender, System.EventArgs args) + 0xd7 bytes
  WindowsBase.dll!System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0xa bytes
  PresentationFramework.dll!System.Windows.Data.CollectionView.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x29 bytes
  PresentationFramework.dll!System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(System.Collections.Specialized.NotifyCollectionChangedEventArgs args, int adjustedOldIndex, int adjustedNewIndex) + 0x202 bytes
  PresentationFramework.dll!System.Windows.Data.ListCollectionView.ProcessCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x132 bytes
  PresentationFramework.dll!System.Windows.Data.CollectionView.OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x5d bytes
  System.dll!System.Collections.ObjectModel.ReadOnlyObservableCollection<System.__Canon>.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x19 bytes
  System.dll!System.Collections.ObjectModel.ReadOnlyObservableCollection<System.__Canon>.HandleCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + 0xe bytes
  System.dll!System.Collections.ObjectModel.ObservableCollection<Overwatch.ELT.AppCommon.Explorer.LayerTviVM>.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + 0x52 bytes
  System.dll!System.Collections.ObjectModel.ObservableCollection<System.__Canon>.MoveItem(int oldIndex, int newIndex) + 0x87 bytes
  System.dll!System.Collections.ObjectModel.ObservableCollection<System.__Canon>.Move(int oldIndex, int newIndex) + 0xe bytes

18 Answers, 1 is accepted

Sort by
0
Tina Stancheva
Telerik team
answered on 21 May 2012, 02:42 PM
Hello Chris,

I wasn't able to reproduce this issue. Can you please take a look at the sample I attached and let me know if I'm missing something? Thank you in advance.

All the best,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Chris
Top achievements
Rank 1
answered on 07 Jun 2012, 04:18 PM
I finally got a chance to take another look at this and I figured out how to reproduce my issue with your sample.

Change the OnMove function to do two sequential moves and you'll get the exception:

private void OnMove(object param)
{
            Items.Move(4, 0);
            Items.Move(4, 0);
}

I can't see any reason why this shouldn't work.
0
Chris
Top achievements
Rank 1
answered on 11 Jun 2012, 04:07 PM
Is there any word on this?  It's high priority for us because it's causing crashes in multiple scenarios.
0
Chris
Top achievements
Rank 1
answered on 11 Jun 2012, 06:30 PM
Interestingly, inverting the indices does not cause a crash:

private void OnMove(object param)
{
            Items.Move(0, 4);
            Items.Move(0, 4);
}

0
Hristo
Telerik team
answered on 12 Jun 2012, 11:59 AM
Hello Chris,

First of all, I would like to take our apologies for the caused inconvenience. It turns out this is a bug in the TreeView virtualization panel.
The virtualization panel keeps a collection of realized items (those items that have generated container). When you call "Move" on your items collection (if the item is realized) a record from the realized containers collection is removed. If the item is going to be realized again (i.e. it is inserted in the visible part of the TreeView) a corresponding record is inserted in the realized containers collection. But the insertion is asynchronous and is happening at later point in time. If you call Move during the interval where item is removed and not still inserted the exception occurs.
I can offer you two workarounds:
1) If you do not need TreeView virtualization you could change the items panel and the exception should go away.
2) If you need TreeView virtualization feature you could try not using the Move method and perform a Remove and Insert instead.

private void OnMove(object param)
{
    //Items.Move(4, 0);
    //Items.Move(4, 0);
    var item4 = Items[4];
    Items.RemoveAt(4);
    Items.Insert(0, item4);
     
    var item3 = Items[4];
    Items.RemoveAt(4);
    Items.Insert(0, item3);
}

Hope this helps. Please let us know if provided workarounds are not applicable or you have any other issues.

Greetings,
Hristo
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Chris
Top achievements
Rank 1
answered on 12 Jun 2012, 01:37 PM
Thanks for the reply.

We absolutely need the virtualization (it's one of the main reasons why we switched to RadTreeView).  The remove/insert may be a viable workaround, but I just hit another crash when we removed all items from the tree and added a new one.  I'm trying to see if I can modify the sample to replicate it.
0
Chris
Top achievements
Rank 1
answered on 12 Jun 2012, 02:45 PM
When do you think you would release a fix for this bug?

Our application isn't going to be released until August, so it's not urgent but it would be nice to know when we could expect a fix.
0
Tina Stancheva
Telerik team
answered on 14 Jun 2012, 01:40 PM
Hello Chris,

We are currently looking into this issue but it seems that it will require an extensive research and at this point we are not sure if we will be able to find and/or implement a fix. This is why I logged the item in our PITS where you can track its progress. We will update the description/status of the item if we manage to find a fix or a better workaround.

Greetings,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Chris
Top achievements
Rank 1
answered on 20 Jun 2012, 07:27 PM
Update:  The crashes related to removing & adding nodes turned out to be a bug in our own code.  Move is still an issue.

Is there any way that I can make sequential Move operations wait for the virtualized panel to update its collection of realized items?
0
Hristo
Telerik team
answered on 25 Jun 2012, 08:20 AM
Hello Chris,

The only approach I managed to get working is to delay the call to second (consequent) Move(). The easiest way to do that is to use a dispatcher. However having a visual in the view model is not considered a best practice, but I suppose you could isolate it some part of the view model. I'm attaching a sample solution demonstrating the workaround. Give it a try a check if it does work in your case.

private void OnMove(object param)
{
    Items.Move(10, 2);
    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
    {
        Items.Move(10, 2);
    }), System.Windows.Threading.DispatcherPriority.Background);
}

The other workaround is to use Remove and Insert operations. I didn't manage to grasp if this approach is fitting your case.

Hope this helps. Please let us know if the suggested workaround is not working or not applicable to your case.

Regards,
Hristo
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Chris
Top achievements
Rank 1
answered on 27 Jun 2012, 02:43 PM
Using the dispatcher worked, thanks.
0
Chris
Top achievements
Rank 1
answered on 07 Aug 2012, 01:48 PM
Is there any word on this issue?

Dispatching sometimes works, but it's a huge juggling act to dispatch all of our additions/removals to background priority.

This is making development really challenging for us because when we hit an exception it takes quite a bit of troubleshooting to figure out if it's the tree control or our own code causing the problem.

0
Tina Stancheva
Telerik team
answered on 07 Aug 2012, 03:09 PM
Hello Chris,

We did an extensive research on this issue but with the current implementation of the virtualization logic of the RadTreeView, we weren't able to find a fix. This means that in order to fix this issue we'll have to implement serious changes in the internal logic of the control. Unfortunately at this point we cannot schedule such a time-consuming task and this is why I wanted to ask you if you can try the approach using Remove and Insert operations instead of the Move operation. Please let us know if this is a viable workaround for you.

Regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Chris
Top achievements
Rank 1
answered on 07 Aug 2012, 03:17 PM
Add/Remove/Insert operations can all trigger the same crash as Move.  It just depends on timing & order of operations.

We're working around it by dispatching with a background priority but asynchronous code is generally more challenging to get right than synchronous code.
0
Tina Stancheva
Telerik team
answered on 08 Aug 2012, 04:02 PM
Hello Chris,

We raised the priority of the issue and we will do our best to provide a fix with the Q3 2012 release. You can track the PITS item for more information on its progress.

Kind regards,
Tina Stancheva
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Chris
Top achievements
Rank 1
answered on 08 Aug 2012, 04:21 PM
Thank you!
0
Axel
Top achievements
Rank 1
answered on 25 Jul 2018, 12:56 PM

Moving an Databound Item repeatedly in an ObservableCollection still causes a virtualized RadTreeView to throw an outOfRange Exception. I run into this Problem with Version 2017.3.1018.45.

Using the Workaround with Remove and Insert works, so it's not urgent. But it still costs me a half day to figure that one out. Is there any Chance this Bug get's fixed or is it fixed already in another Version?

0
Martin Ivanov
Telerik team
answered on 30 Jul 2018, 08:17 AM
Hello Axel,

I've tested this case but the out-of-range exception is not thrown on my side. However, I've reproduced an InvalidOperationException which I'll guess is caused from the same issue. I've logged the issue in the feedback portal where you can track its status. However, currently I can't give you a timeframe when this will be fixed. I could recommend you to follow the feedback item so that you are notified when there is a change in its status. In the meantime you can use the workaround with the dispatcher.

I also updated you Telerik points as a small gesture of gratitude for reporting this.

Regards,
Martin Ivanov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
TreeView
Asked by
Chris
Top achievements
Rank 1
Answers by
Tina Stancheva
Telerik team
Chris
Top achievements
Rank 1
Hristo
Telerik team
Axel
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or