<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
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 >>
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.
private void OnMove(object param)
{
Items.Move(0, 4);
Items.Move(0, 4);
}
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.
Hristo
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
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.
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.
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 >>
Is there any way that I can make sequential Move operations wait for the virtualized panel to update its collection of realized items?
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 >>
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.
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.
We're working around it by dispatching with a background priority but asynchronous code is generally more challenging to get right than synchronous code.
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.
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?
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